summaryrefslogtreecommitdiff
path: root/slideshow/source
diff options
context:
space:
mode:
Diffstat (limited to 'slideshow/source')
-rw-r--r--slideshow/source/engine/OGLTrans/OGLTrans_Shaders.cxx142
-rw-r--r--slideshow/source/engine/OGLTrans/OGLTrans_Shaders.hxx71
-rw-r--r--slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.cxx1317
-rw-r--r--slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.hxx508
-rw-r--r--slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx1500
-rw-r--r--slideshow/source/engine/OGLTrans/exports.dxp3
-rw-r--r--slideshow/source/engine/OGLTrans/makefile.mk80
-rw-r--r--slideshow/source/engine/activities/accumulation.hxx95
-rw-r--r--slideshow/source/engine/activities/activitiesfactory.cxx989
-rw-r--r--slideshow/source/engine/activities/activitybase.cxx249
-rw-r--r--slideshow/source/engine/activities/activitybase.hxx154
-rw-r--r--slideshow/source/engine/activities/activityparameters.hxx145
-rw-r--r--slideshow/source/engine/activities/continuousactivitybase.cxx57
-rw-r--r--slideshow/source/engine/activities/continuousactivitybase.hxx76
-rw-r--r--slideshow/source/engine/activities/continuouskeytimeactivitybase.cxx79
-rw-r--r--slideshow/source/engine/activities/continuouskeytimeactivitybase.hxx86
-rw-r--r--slideshow/source/engine/activities/discreteactivitybase.cxx209
-rw-r--r--slideshow/source/engine/activities/discreteactivitybase.hxx90
-rw-r--r--slideshow/source/engine/activities/interpolation.hxx197
-rw-r--r--slideshow/source/engine/activities/makefile.mk53
-rw-r--r--slideshow/source/engine/activities/simplecontinuousactivitybase.cxx261
-rw-r--r--slideshow/source/engine/activities/simplecontinuousactivitybase.hxx90
-rw-r--r--slideshow/source/engine/activitiesqueue.cxx213
-rw-r--r--slideshow/source/engine/animatedsprite.cxx228
-rw-r--r--slideshow/source/engine/animationfactory.cxx1389
-rw-r--r--slideshow/source/engine/animationnodes/animationaudionode.cxx183
-rw-r--r--slideshow/source/engine/animationnodes/animationaudionode.hxx80
-rw-r--r--slideshow/source/engine/animationnodes/animationbasenode.cxx492
-rw-r--r--slideshow/source/engine/animationnodes/animationbasenode.hxx113
-rw-r--r--slideshow/source/engine/animationnodes/animationcolornode.cxx139
-rw-r--r--slideshow/source/engine/animationnodes/animationcolornode.hxx65
-rw-r--r--slideshow/source/engine/animationnodes/animationcommandnode.cxx137
-rw-r--r--slideshow/source/engine/animationnodes/animationcommandnode.hxx72
-rw-r--r--slideshow/source/engine/animationnodes/animationnodefactory.cxx622
-rw-r--r--slideshow/source/engine/animationnodes/animationpathmotionnode.cxx69
-rw-r--r--slideshow/source/engine/animationnodes/animationpathmotionnode.hxx68
-rw-r--r--slideshow/source/engine/animationnodes/animationsetnode.cxx215
-rw-r--r--slideshow/source/engine/animationnodes/animationsetnode.hxx60
-rw-r--r--slideshow/source/engine/animationnodes/animationtransformnode.cxx117
-rw-r--r--slideshow/source/engine/animationnodes/animationtransformnode.hxx69
-rw-r--r--slideshow/source/engine/animationnodes/animationtransitionfilternode.cxx62
-rw-r--r--slideshow/source/engine/animationnodes/animationtransitionfilternode.hxx70
-rw-r--r--slideshow/source/engine/animationnodes/basecontainernode.cxx177
-rw-r--r--slideshow/source/engine/animationnodes/basecontainernode.hxx107
-rw-r--r--slideshow/source/engine/animationnodes/basenode.cxx771
-rw-r--r--slideshow/source/engine/animationnodes/basenode.hxx231
-rw-r--r--slideshow/source/engine/animationnodes/generateevent.cxx248
-rw-r--r--slideshow/source/engine/animationnodes/generateevent.hxx64
-rw-r--r--slideshow/source/engine/animationnodes/makefile.mk61
-rw-r--r--slideshow/source/engine/animationnodes/nodetools.cxx131
-rw-r--r--slideshow/source/engine/animationnodes/nodetools.hxx91
-rw-r--r--slideshow/source/engine/animationnodes/paralleltimecontainer.cxx71
-rw-r--r--slideshow/source/engine/animationnodes/paralleltimecontainer.hxx65
-rw-r--r--slideshow/source/engine/animationnodes/propertyanimationnode.cxx117
-rw-r--r--slideshow/source/engine/animationnodes/propertyanimationnode.hxx60
-rw-r--r--slideshow/source/engine/animationnodes/sequentialtimecontainer.cxx164
-rw-r--r--slideshow/source/engine/animationnodes/sequentialtimecontainer.hxx77
-rw-r--r--slideshow/source/engine/animationnodes/setactivity.hxx158
-rw-r--r--slideshow/source/engine/arith-grammar.txt61
-rw-r--r--slideshow/source/engine/attributemap.cxx126
-rw-r--r--slideshow/source/engine/color.cxx470
-rw-r--r--slideshow/source/engine/debug.cxx327
-rw-r--r--slideshow/source/engine/delayevent.cxx71
-rw-r--r--slideshow/source/engine/effectrewinder.cxx436
-rw-r--r--slideshow/source/engine/effectrewinder.hxx185
-rw-r--r--slideshow/source/engine/eventmultiplexer.cxx1280
-rw-r--r--slideshow/source/engine/eventqueue.cxx338
-rw-r--r--slideshow/source/engine/expressionnodefactory.cxx282
-rw-r--r--slideshow/source/engine/makefile.mk102
-rw-r--r--slideshow/source/engine/rehearsetimingsactivity.cxx584
-rw-r--r--slideshow/source/engine/rehearsetimingsactivity.hxx150
-rw-r--r--slideshow/source/engine/screenupdater.cxx271
-rw-r--r--slideshow/source/engine/shapeattributelayer.cxx859
-rw-r--r--slideshow/source/engine/shapes/appletshape.cxx333
-rw-r--r--slideshow/source/engine/shapes/appletshape.hxx63
-rw-r--r--slideshow/source/engine/shapes/backgroundshape.cxx339
-rw-r--r--slideshow/source/engine/shapes/backgroundshape.hxx65
-rw-r--r--slideshow/source/engine/shapes/drawinglayeranimation.cxx986
-rw-r--r--slideshow/source/engine/shapes/drawinglayeranimation.hxx50
-rw-r--r--slideshow/source/engine/shapes/drawshape.cxx1481
-rw-r--r--slideshow/source/engine/shapes/drawshape.hxx385
-rw-r--r--slideshow/source/engine/shapes/drawshapesubsetting.cxx868
-rw-r--r--slideshow/source/engine/shapes/drawshapesubsetting.hxx291
-rw-r--r--slideshow/source/engine/shapes/externalshapebase.cxx249
-rw-r--r--slideshow/source/engine/shapes/externalshapebase.hxx148
-rw-r--r--slideshow/source/engine/shapes/gdimtftools.cxx551
-rw-r--r--slideshow/source/engine/shapes/gdimtftools.hxx158
-rw-r--r--slideshow/source/engine/shapes/intrinsicanimationactivity.cxx293
-rw-r--r--slideshow/source/engine/shapes/intrinsicanimationactivity.hxx79
-rw-r--r--slideshow/source/engine/shapes/makefile.mk60
-rw-r--r--slideshow/source/engine/shapes/mediashape.cxx300
-rw-r--r--slideshow/source/engine/shapes/mediashape.hxx58
-rw-r--r--slideshow/source/engine/shapes/shapeimporter.cxx679
-rw-r--r--slideshow/source/engine/shapes/viewappletshape.cxx303
-rw-r--r--slideshow/source/engine/shapes/viewappletshape.hxx172
-rw-r--r--slideshow/source/engine/shapes/viewbackgroundshape.cxx215
-rw-r--r--slideshow/source/engine/shapes/viewbackgroundshape.hxx107
-rw-r--r--slideshow/source/engine/shapes/viewmediashape.cxx575
-rw-r--r--slideshow/source/engine/shapes/viewmediashape.hxx182
-rw-r--r--slideshow/source/engine/shapes/viewshape.cxx901
-rw-r--r--slideshow/source/engine/shapes/viewshape.hxx343
-rw-r--r--slideshow/source/engine/shapesubset.cxx144
-rw-r--r--slideshow/source/engine/slide/layer.cxx367
-rw-r--r--slideshow/source/engine/slide/layer.hxx319
-rw-r--r--slideshow/source/engine/slide/layermanager.cxx926
-rw-r--r--slideshow/source/engine/slide/layermanager.hxx388
-rw-r--r--slideshow/source/engine/slide/makefile.mk51
-rw-r--r--slideshow/source/engine/slide/shapemanagerimpl.cxx464
-rw-r--r--slideshow/source/engine/slide/shapemanagerimpl.hxx212
-rw-r--r--slideshow/source/engine/slide/slideanimations.cxx134
-rw-r--r--slideshow/source/engine/slide/slideanimations.hxx128
-rw-r--r--slideshow/source/engine/slide/slideimpl.cxx1286
-rw-r--r--slideshow/source/engine/slide/userpaintoverlay.cxx507
-rw-r--r--slideshow/source/engine/slide/userpaintoverlay.hxx92
-rw-r--r--slideshow/source/engine/slidebitmap.cxx135
-rw-r--r--slideshow/source/engine/slideshowcontext.cxx79
-rw-r--r--slideshow/source/engine/slideshowimpl.cxx2538
-rw-r--r--slideshow/source/engine/slideview.cxx1198
-rw-r--r--slideshow/source/engine/smilfunctionparser.cxx641
-rw-r--r--slideshow/source/engine/soundplayer.cxx186
-rw-r--r--slideshow/source/engine/sp_debug.cxx300
-rw-r--r--slideshow/source/engine/tools.cxx856
-rw-r--r--slideshow/source/engine/transitions/barndoorwipe.cxx68
-rw-r--r--slideshow/source/engine/transitions/barndoorwipe.hxx58
-rw-r--r--slideshow/source/engine/transitions/barwipepolypolygon.cxx59
-rw-r--r--slideshow/source/engine/transitions/barwipepolypolygon.hxx58
-rw-r--r--slideshow/source/engine/transitions/boxwipe.cxx60
-rw-r--r--slideshow/source/engine/transitions/boxwipe.hxx57
-rw-r--r--slideshow/source/engine/transitions/checkerboardwipe.cxx68
-rw-r--r--slideshow/source/engine/transitions/checkerboardwipe.hxx60
-rw-r--r--slideshow/source/engine/transitions/clippingfunctor.cxx241
-rw-r--r--slideshow/source/engine/transitions/clippingfunctor.hxx98
-rw-r--r--slideshow/source/engine/transitions/clockwipe.cxx77
-rw-r--r--slideshow/source/engine/transitions/clockwipe.hxx53
-rw-r--r--slideshow/source/engine/transitions/combtransition.cxx199
-rw-r--r--slideshow/source/engine/transitions/combtransition.hxx75
-rw-r--r--slideshow/source/engine/transitions/doublediamondwipe.cxx69
-rw-r--r--slideshow/source/engine/transitions/doublediamondwipe.hxx56
-rw-r--r--slideshow/source/engine/transitions/ellipsewipe.cxx55
-rw-r--r--slideshow/source/engine/transitions/ellipsewipe.hxx51
-rw-r--r--slideshow/source/engine/transitions/fanwipe.cxx74
-rw-r--r--slideshow/source/engine/transitions/fanwipe.hxx54
-rw-r--r--slideshow/source/engine/transitions/figurewipe.cxx132
-rw-r--r--slideshow/source/engine/transitions/figurewipe.hxx58
-rw-r--r--slideshow/source/engine/transitions/fourboxwipe.cxx88
-rw-r--r--slideshow/source/engine/transitions/fourboxwipe.hxx58
-rw-r--r--slideshow/source/engine/transitions/iriswipe.cxx55
-rw-r--r--slideshow/source/engine/transitions/iriswipe.hxx55
-rw-r--r--slideshow/source/engine/transitions/makefile.mk73
-rw-r--r--slideshow/source/engine/transitions/parametricpolypolygon.hxx101
-rw-r--r--slideshow/source/engine/transitions/parametricpolypolygonfactory.cxx315
-rw-r--r--slideshow/source/engine/transitions/parametricpolypolygonfactory.hxx57
-rw-r--r--slideshow/source/engine/transitions/pinwheelwipe.cxx62
-rw-r--r--slideshow/source/engine/transitions/pinwheelwipe.hxx54
-rw-r--r--slideshow/source/engine/transitions/randomwipe.cxx97
-rw-r--r--slideshow/source/engine/transitions/randomwipe.hxx61
-rw-r--r--slideshow/source/engine/transitions/shapetransitionfactory.cxx411
-rw-r--r--slideshow/source/engine/transitions/slidechangebase.cxx538
-rw-r--r--slideshow/source/engine/transitions/slidechangebase.hxx211
-rw-r--r--slideshow/source/engine/transitions/slidetransitionfactory.cxx1172
-rw-r--r--slideshow/source/engine/transitions/snakewipe.cxx247
-rw-r--r--slideshow/source/engine/transitions/snakewipe.hxx79
-rw-r--r--slideshow/source/engine/transitions/spiralwipe.cxx134
-rw-r--r--slideshow/source/engine/transitions/spiralwipe.hxx71
-rw-r--r--slideshow/source/engine/transitions/sweepwipe.cxx87
-rw-r--r--slideshow/source/engine/transitions/sweepwipe.hxx56
-rw-r--r--slideshow/source/engine/transitions/transitionfactorytab.cxx2149
-rw-r--r--slideshow/source/engine/transitions/transitiontools.cxx72
-rw-r--r--slideshow/source/engine/transitions/transitiontools.hxx58
-rw-r--r--slideshow/source/engine/transitions/veewipe.cxx56
-rw-r--r--slideshow/source/engine/transitions/veewipe.hxx54
-rw-r--r--slideshow/source/engine/transitions/waterfallwipe.cxx80
-rw-r--r--slideshow/source/engine/transitions/waterfallwipe.hxx55
-rw-r--r--slideshow/source/engine/transitions/zigzagwipe.cxx85
-rw-r--r--slideshow/source/engine/transitions/zigzagwipe.hxx63
-rw-r--r--slideshow/source/engine/unoviewcontainer.cxx152
-rw-r--r--slideshow/source/engine/usereventqueue.cxx1009
-rw-r--r--slideshow/source/engine/waitsymbol.cxx211
-rw-r--r--slideshow/source/engine/waitsymbol.hxx111
-rw-r--r--slideshow/source/engine/wakeupevent.cxx102
-rw-r--r--slideshow/source/inc/activitiesfactory.hxx336
-rw-r--r--slideshow/source/inc/activitiesqueue.hxx133
-rw-r--r--slideshow/source/inc/activity.hxx103
-rw-r--r--slideshow/source/inc/animatableshape.hxx91
-rw-r--r--slideshow/source/inc/animatedsprite.hxx189
-rw-r--r--slideshow/source/inc/animation.hxx100
-rw-r--r--slideshow/source/inc/animationactivity.hxx78
-rw-r--r--slideshow/source/inc/animationeventhandler.hxx74
-rw-r--r--slideshow/source/inc/animationfactory.hxx160
-rw-r--r--slideshow/source/inc/animationfunction.hxx74
-rw-r--r--slideshow/source/inc/animationnode.hxx165
-rw-r--r--slideshow/source/inc/animationnodefactory.hxx81
-rw-r--r--slideshow/source/inc/attributableshape.hxx231
-rw-r--r--slideshow/source/inc/attributemap.hxx83
-rw-r--r--slideshow/source/inc/boolanimation.hxx80
-rw-r--r--slideshow/source/inc/coloranimation.hxx80
-rw-r--r--slideshow/source/inc/cursormanager.hxx75
-rw-r--r--slideshow/source/inc/debug.hxx80
-rw-r--r--slideshow/source/inc/delayevent.hxx160
-rw-r--r--slideshow/source/inc/disposable.hxx68
-rw-r--r--slideshow/source/inc/doctreenode.hxx144
-rw-r--r--slideshow/source/inc/doctreenodesupplier.hxx154
-rw-r--r--slideshow/source/inc/enumanimation.hxx82
-rw-r--r--slideshow/source/inc/event.hxx95
-rw-r--r--slideshow/source/inc/eventhandler.hxx70
-rw-r--r--slideshow/source/inc/eventmultiplexer.hxx663
-rw-r--r--slideshow/source/inc/eventqueue.hxx159
-rw-r--r--slideshow/source/inc/expressionnode.hxx69
-rw-r--r--slideshow/source/inc/expressionnodefactory.hxx85
-rw-r--r--slideshow/source/inc/externalmediashape.hxx94
-rw-r--r--slideshow/source/inc/framerate.hxx56
-rw-r--r--slideshow/source/inc/hslcolor.hxx126
-rw-r--r--slideshow/source/inc/hslcoloranimation.hxx80
-rw-r--r--slideshow/source/inc/hyperlinkarea.hxx107
-rw-r--r--slideshow/source/inc/hyperlinkhandler.hxx71
-rw-r--r--slideshow/source/inc/interruptabledelayevent.hxx153
-rw-r--r--slideshow/source/inc/intrinsicanimationeventhandler.hxx63
-rw-r--r--slideshow/source/inc/listenercontainer.hxx317
-rw-r--r--slideshow/source/inc/listenercontainerimpl.hxx227
-rw-r--r--slideshow/source/inc/mouseeventhandler.hxx156
-rw-r--r--slideshow/source/inc/numberanimation.hxx82
-rw-r--r--slideshow/source/inc/pairanimation.hxx81
-rw-r--r--slideshow/source/inc/pauseeventhandler.hxx71
-rw-r--r--slideshow/source/inc/rgbcolor.hxx128
-rw-r--r--slideshow/source/inc/screenupdater.hxx142
-rw-r--r--slideshow/source/inc/shape.hxx276
-rw-r--r--slideshow/source/inc/shapeattributelayer.hxx559
-rw-r--r--slideshow/source/inc/shapeattributelayerholder.hxx113
-rw-r--r--slideshow/source/inc/shapecursoreventhandler.hxx70
-rw-r--r--slideshow/source/inc/shapeimporter.hxx158
-rw-r--r--slideshow/source/inc/shapelistenereventhandler.hxx78
-rw-r--r--slideshow/source/inc/shapemanager.hxx128
-rw-r--r--slideshow/source/inc/shapemaps.hxx64
-rw-r--r--slideshow/source/inc/shapesubset.hxx153
-rw-r--r--slideshow/source/inc/slide.hxx220
-rw-r--r--slideshow/source/inc/slidebitmap.hxx98
-rw-r--r--slideshow/source/inc/slideshowcontext.hxx121
-rw-r--r--slideshow/source/inc/slideshowexceptions.hxx56
-rw-r--r--slideshow/source/inc/slideview.hxx64
-rw-r--r--slideshow/source/inc/smilfunctionparser.hxx170
-rw-r--r--slideshow/source/inc/soundplayer.hxx121
-rw-r--r--slideshow/source/inc/state.hxx76
-rw-r--r--slideshow/source/inc/stringanimation.hxx80
-rw-r--r--slideshow/source/inc/subsettableshapemanager.hxx129
-rw-r--r--slideshow/source/inc/tools.hxx407
-rw-r--r--slideshow/source/inc/transitionfactory.hxx151
-rw-r--r--slideshow/source/inc/transitioninfo.hxx163
-rw-r--r--slideshow/source/inc/unoview.hxx88
-rw-r--r--slideshow/source/inc/unoviewcontainer.hxx113
-rw-r--r--slideshow/source/inc/usereventqueue.hxx329
-rw-r--r--slideshow/source/inc/userpainteventhandler.hxx68
-rw-r--r--slideshow/source/inc/view.hxx98
-rw-r--r--slideshow/source/inc/vieweventhandler.hxx102
-rw-r--r--slideshow/source/inc/viewlayer.hxx178
-rw-r--r--slideshow/source/inc/viewrepainthandler.hxx76
-rw-r--r--slideshow/source/inc/viewupdate.hxx79
-rw-r--r--slideshow/source/inc/wakeupevent.hxx96
257 files changed, 60951 insertions, 0 deletions
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_Shaders.cxx b/slideshow/source/engine/OGLTrans/OGLTrans_Shaders.cxx
new file mode 100644
index 000000000000..76b893a83b9e
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/OGLTrans_Shaders.cxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/diagnose.hxx>
+
+#include "OGLTrans_Shaders.hxx"
+
+namespace unx
+{
+#include <GL/glx.h>
+#include <GL/glxext.h>
+}
+
+bool OGLShaders::cbInitialized = false;
+
+#ifdef GL_VERSION_2_0
+
+PFNGLCREATESHADERPROC OGLShaders::glCreateShader = NULL;
+PFNGLSHADERSOURCEPROC OGLShaders::glShaderSource = NULL;
+PFNGLCOMPILESHADERPROC OGLShaders::glCompileShader = NULL;
+PFNGLGETSHADERIVPROC OGLShaders::glGetShaderiv = NULL;
+PFNGLGETSHADERINFOLOGPROC OGLShaders::glGetShaderInfoLog = NULL;
+PFNGLDELETESHADERPROC OGLShaders::glDeleteShader = NULL;
+PFNGLCREATEPROGRAMPROC OGLShaders::glCreateProgram = NULL;
+PFNGLATTACHSHADERPROC OGLShaders::glAttachShader = NULL;
+PFNGLLINKPROGRAMPROC OGLShaders::glLinkProgram = NULL;
+PFNGLGETPROGRAMIVPROC OGLShaders::glGetProgramiv = NULL;
+PFNGLGETPROGRAMINFOLOGPROC OGLShaders::glGetProgramInfoLog = NULL;
+PFNGLUSEPROGRAMPROC OGLShaders::glUseProgram = NULL;
+PFNGLDELETEPROGRAMPROC OGLShaders::glDeleteProgram = NULL;
+PFNGLGETUNIFORMLOCATIONPROC OGLShaders::glGetUniformLocation = NULL;
+PFNGLUNIFORM1IPROC OGLShaders::glUniform1i = NULL;
+PFNGLUNIFORM1FPROC OGLShaders::glUniform1f = NULL;
+#endif
+
+bool OGLShaders::Initialize()
+{
+#ifdef GL_VERSION_2_0
+ if( !cbInitialized ) {
+ glCreateShader = (PFNGLCREATESHADERPROC) unx::glXGetProcAddress( (unsigned char *) "glCreateShader" );
+ glShaderSource = (PFNGLSHADERSOURCEPROC) unx::glXGetProcAddress( (unsigned char *) "glShaderSource" );
+ glCompileShader = (PFNGLCOMPILESHADERPROC) unx::glXGetProcAddress( (unsigned char *) "glCompileShader" );
+ glGetShaderiv = (PFNGLGETSHADERIVPROC) unx::glXGetProcAddress( (unsigned char *) "glGetShaderiv" );
+ glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) unx::glXGetProcAddress( (unsigned char *) "glGetShaderInfoLog" );
+ glDeleteShader = (PFNGLDELETESHADERPROC) unx::glXGetProcAddress( (unsigned char *) "glDeleteShader" );
+ glCreateProgram = (PFNGLCREATEPROGRAMPROC) unx::glXGetProcAddress( (unsigned char *) "glCreateProgram" );
+ glAttachShader = (PFNGLATTACHSHADERPROC) unx::glXGetProcAddress( (unsigned char *) "glAttachShader" );
+ glLinkProgram = (PFNGLLINKPROGRAMPROC) unx::glXGetProcAddress( (unsigned char *) "glLinkProgram" );
+ glGetProgramiv = (PFNGLGETPROGRAMIVPROC) unx::glXGetProcAddress( (unsigned char *) "glGetProgramiv" );
+ glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) unx::glXGetProcAddress( (unsigned char *) "glGetProgramInfoLog" );
+ glUseProgram = (PFNGLUSEPROGRAMPROC) unx::glXGetProcAddress( (unsigned char *) "glUseProgram" );
+ glDeleteProgram = (PFNGLDELETEPROGRAMPROC) unx::glXGetProcAddress( (unsigned char *) "glDeleteProgram" );
+ glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) unx::glXGetProcAddress( (unsigned char *) "glGetUniformLocation" );
+ glUniform1i = (PFNGLUNIFORM1IPROC) unx::glXGetProcAddress( (unsigned char *) "glUniform1i" );
+ glUniform1f = (PFNGLUNIFORM1FPROC) unx::glXGetProcAddress( (unsigned char *) "glUniform1f" );
+ cbInitialized = true;
+ }
+
+ return glCreateShader != NULL;
+#else
+ return false;
+#endif
+}
+
+GLuint OGLShaders::LinkProgram( const char *vertexShader, const char *fragmentShader )
+{
+#ifdef GL_VERSION_2_0
+ if( !Initialize() )
+ return 0;
+
+ GLhandleARB vertexObject, fragmentObject, programObject;
+ GLint vertexCompiled, fragmentCompiled, programLinked;
+ char log[1024];
+
+ vertexObject = glCreateShader( GL_VERTEX_SHADER );
+ fragmentObject = glCreateShader( GL_FRAGMENT_SHADER );
+ OSL_TRACE("checkpoint 1: shaders created (%d) vertex: %d fragment: %d", glGetError() == GL_NO_ERROR, vertexObject, fragmentObject );
+
+
+ glShaderSource( vertexObject, 1, &vertexShader, NULL );
+ glShaderSource( fragmentObject, 1, &fragmentShader, NULL );
+
+ glCompileShader( vertexObject );
+ glGetShaderInfoLog( vertexObject, sizeof( log ), NULL, log );
+ OSL_TRACE("vertex compile log: %s", log);
+ glGetShaderiv( vertexObject, GL_COMPILE_STATUS, &vertexCompiled );
+ glCompileShader( fragmentObject );
+ glGetShaderInfoLog( fragmentObject, sizeof( log ), NULL, log );
+ OSL_TRACE("fragment compile log: %s", log);
+ glGetShaderiv( fragmentObject, GL_COMPILE_STATUS, &fragmentCompiled );
+
+ if( !vertexCompiled || !fragmentCompiled )
+ return 0;
+
+ OSL_TRACE("checkpoint 2: shaders compiled (%d)", glGetError() == GL_NO_ERROR);
+
+ programObject = glCreateProgram();
+ glAttachShader( programObject, vertexObject );
+ glAttachShader( programObject, fragmentObject );
+
+ glLinkProgram( programObject );
+ glGetProgramInfoLog( programObject, sizeof( log ), NULL, log );
+ OSL_TRACE("program link log: %s", log);
+ glGetProgramiv( programObject, GL_LINK_STATUS, &programLinked );
+
+ if( !programLinked )
+ return 0;
+
+ OSL_TRACE("checkpoint 3: program linked (%d)", glGetError() == GL_NO_ERROR);
+
+ return programObject;
+#else
+ return 0;
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_Shaders.hxx b/slideshow/source/engine/OGLTrans/OGLTrans_Shaders.hxx
new file mode 100644
index 000000000000..e42c2a0f7a42
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/OGLTrans_Shaders.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_OGLTRANS_SHADERS_HXX_
+#define INCLUDED_OGLTRANS_SHADERS_HXX_
+
+#define GL_GLEXT_PROTOTYPES 1
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+class OGLShaders {
+ static bool Initialize();
+ static bool cbInitialized;
+
+public:
+
+ static GLuint LinkProgram( const char *vertexShader, const char *fragmentShader );
+
+ /** GL shader functions
+ */
+#ifdef GL_VERSION_2_0
+
+ static PFNGLCREATESHADERPROC glCreateShader;
+ static PFNGLSHADERSOURCEPROC glShaderSource;
+ static PFNGLCOMPILESHADERPROC glCompileShader;
+ static PFNGLGETSHADERIVPROC glGetShaderiv;
+ static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
+ static PFNGLDELETESHADERPROC glDeleteShader;
+
+ static PFNGLCREATEPROGRAMPROC glCreateProgram;
+ static PFNGLATTACHSHADERPROC glAttachShader;
+ static PFNGLLINKPROGRAMPROC glLinkProgram;
+ static PFNGLGETPROGRAMIVPROC glGetProgramiv;
+ static PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
+ static PFNGLUSEPROGRAMPROC glUseProgram;
+ static PFNGLDELETEPROGRAMPROC glDeleteProgram;
+
+ static PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
+ static PFNGLUNIFORM1IPROC glUniform1i;
+ static PFNGLUNIFORM1FPROC glUniform1f;
+#endif
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.cxx b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.cxx
new file mode 100644
index 000000000000..c3d15073d632
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.cxx
@@ -0,0 +1,1317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "OGLTrans_Shaders.hxx"
+#include "OGLTrans_TransitionImpl.hxx"
+#include <GL/gl.h>
+#include <math.h>
+
+
+void OGLTransitionImpl::clear()
+{
+ for(unsigned int i( 0 ); i < OverallOperations.size(); ++i)
+ delete OverallOperations[i];
+ OverallOperations.clear();
+ maLeavingSlidePrimitives.clear();
+ maEnteringSlidePrimitives.clear();
+ for(unsigned int i(0); i < maSceneObjects.size(); ++i)
+ delete maSceneObjects[i];
+ maSceneObjects.clear();
+
+ mbReflectSlides = false;
+
+#ifdef GL_VERSION_2_0
+ if( mProgramObject ) {
+ OGLShaders::glDeleteProgram( mProgramObject );
+ mProgramObject = 0;
+ }
+
+ if( mVertexObject ) {
+ OGLShaders::glDeleteShader( mVertexObject );
+ mVertexObject = 0;
+ }
+
+ if( mFragmentObject ) {
+ OGLShaders::glDeleteShader( mFragmentObject );
+ mFragmentObject = 0;
+ }
+#endif
+
+ if( maHelperTexture ) {
+ glDeleteTextures( 1, &maHelperTexture );
+ maHelperTexture = 0;
+ }
+
+ if( mmClearTransition )
+ (this->*mmClearTransition)();
+}
+
+OGLTransitionImpl::~OGLTransitionImpl()
+{
+ clear();
+}
+
+void OGLTransitionImpl::prepare( ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex )
+{
+ for(unsigned int i(0); i < maSceneObjects.size(); ++i) {
+ maSceneObjects[i]->prepare();
+ }
+
+ if( mmPrepareTransition )
+ (this->*mmPrepareTransition)( glLeavingSlideTex, glEnteringSlideTex );
+}
+
+void OGLTransitionImpl::finish()
+{
+ for(unsigned int i(0); i < maSceneObjects.size(); ++i) {
+ maSceneObjects[i]->finish();
+ }
+}
+
+static void blendSlide( double depth )
+{
+ double showHeight = -1 + depth*2;
+ GLfloat reflectionColor[] = {0, 0, 0, 0.25};
+
+ glDisable( GL_DEPTH_TEST );
+ glBegin( GL_QUADS );
+ glColor4fv( reflectionColor );
+ glVertex3f( -1, -1, 0 );
+ glColor4f( 0, 0, 0, 1 );
+ glVertex3f(-1, showHeight, 0 );
+ glVertex3f( 1, showHeight, 0 );
+ glColor4fv( reflectionColor );
+ glVertex3f( 1, -1, 0 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor4f( 0, 0, 0, 1 );
+ glVertex3f( -1, showHeight, 0 );
+ glVertex3f( -1, 1, 0 );
+ glVertex3f( 1, 1, 0 );
+ glVertex3f( 1, showHeight, 0 );
+ glEnd();
+ glEnable( GL_DEPTH_TEST );
+}
+
+static void slideShadow( double nTime, Primitive& primitive, double sw, double sh )
+{
+ double reflectionDepth = 0.3;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_LIGHTING);
+
+ glPushMatrix();
+ primitive.applyOperations( nTime, sw, sh );
+ blendSlide( reflectionDepth );
+ glPopMatrix();
+
+ glDisable(GL_BLEND);
+ glEnable(GL_LIGHTING);
+}
+
+void OGLTransitionImpl::display( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex,
+ double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
+{
+ double SlideWidthScale, SlideHeightScale;
+
+ SlideWidthScale = SlideWidth/DispWidth;
+ SlideHeightScale = SlideHeight/DispHeight;
+
+ if( mmPrepare ) {
+ clear();
+ (this->*mmPrepare)( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
+ }
+
+ glPushMatrix();
+ displaySlides( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale );
+ displayScene( nTime, SlideWidth, SlideHeight, DispWidth, DispHeight );
+ glPopMatrix();
+}
+
+void OGLTransitionImpl::applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale )
+{
+ for(unsigned int i(0); i < OverallOperations.size(); ++i)
+ OverallOperations[i]->interpolate(nTime,SlideWidthScale,SlideHeightScale);
+}
+
+void OGLTransitionImpl::displaySlide( double nTime, ::sal_Int32 glSlideTex, std::vector<Primitive>& primitives,
+ double SlideWidthScale, double SlideHeightScale )
+{
+ //TODO change to foreach
+ glBindTexture(GL_TEXTURE_2D, glSlideTex);
+
+ // display slide reflection
+ // note that depth test is turned off while blending the shadow
+ // so the slides has to be rendered in right order, see rochade as example
+ if( mbReflectSlides ) {
+ double surfaceLevel = -0.04;
+
+ /* reflected slides */
+ glPushMatrix();
+
+ glScaled( 1, -1, 1 );
+ glTranslated( 0, 2 - surfaceLevel, 0 );
+
+ glCullFace(GL_FRONT);
+ for(unsigned int i(0); i < primitives.size(); ++i)
+ primitives[i].display(nTime, SlideWidthScale, SlideHeightScale);
+ glCullFace(GL_BACK);
+
+ slideShadow( nTime, primitives[0], SlideWidthScale, SlideHeightScale );
+
+ glPopMatrix();
+ }
+
+ for(unsigned int i(0); i < primitives.size(); ++i)
+ primitives[i].display(nTime, SlideWidthScale, SlideHeightScale);
+}
+
+void OGLTransitionImpl::displaySlides( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex,
+ double SlideWidthScale, double SlideHeightScale )
+{
+ if( mmDisplaySlides )
+ (this->*mmDisplaySlides)( nTime, glLeavingSlideTex, glEnteringSlideTex, SlideWidthScale, SlideHeightScale );
+ else {
+ applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
+
+ glEnable(GL_TEXTURE_2D);
+ displaySlide( nTime, glLeavingSlideTex, maLeavingSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ displaySlide( nTime, glEnteringSlideTex, maEnteringSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ }
+}
+
+void OGLTransitionImpl::displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
+{
+ glEnable(GL_TEXTURE_2D);
+ for(unsigned int i(0); i < maSceneObjects.size(); ++i)
+ maSceneObjects[i]->display(nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
+}
+
+void Primitive::display(double nTime, double WidthScale, double HeightScale)
+{
+ glPushMatrix();
+
+ applyOperations( nTime, WidthScale, HeightScale );
+
+ glEnableClientState( GL_VERTEX_ARRAY );
+ if(!Normals.empty())
+ {
+ glNormalPointer( GL_DOUBLE , 0 , &Normals[0] );
+ glEnableClientState( GL_NORMAL_ARRAY );
+ }
+ glEnableClientState( GL_TEXTURE_COORD_ARRAY );
+ glTexCoordPointer( 2, GL_DOUBLE, 0, &TexCoords[0] );
+ glVertexPointer( 3, GL_DOUBLE, 0, &Vertices[0] );
+ glDrawArrays( GL_TRIANGLES, 0, Vertices.size() );
+ glPopMatrix();
+}
+
+void Primitive::applyOperations(double nTime, double WidthScale, double HeightScale)
+{
+ for(unsigned int i(0); i < Operations.size(); ++i)
+ Operations[i]->interpolate( nTime ,WidthScale,HeightScale);
+ glScaled(WidthScale,HeightScale,1);
+}
+
+Primitive::~Primitive()
+{
+ for(unsigned int i( 0 ); i < Operations.size(); ++i)
+ delete Operations[i];
+}
+
+
+void SceneObject::display(double nTime, double /* SlideWidth */, double /* SlideHeight */, double DispWidth, double DispHeight )
+{
+ for(unsigned int i(0); i < maPrimitives.size(); ++i) {
+ // fixme: allow various model spaces, now we make it so that
+ // it is regular -1,-1 to 1,1, where the whole display fits in
+ glPushMatrix();
+ if (DispHeight > DispWidth)
+ glScaled(DispHeight/DispWidth, 1, 1);
+ else
+ glScaled(1, DispWidth/DispHeight, 1);
+ maPrimitives[i].display(nTime, 1, 1);
+ glPopMatrix();
+ }
+}
+
+void SceneObject::pushPrimitive(const Primitive &p)
+{
+ maPrimitives.push_back(p);
+}
+
+SceneObject::SceneObject()
+ : maPrimitives()
+{
+}
+
+Iris::Iris()
+ : SceneObject ()
+{
+}
+
+void Iris::display(double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight )
+{
+ glBindTexture(GL_TEXTURE_2D, maTexture);
+ SceneObject::display(nTime, SlideWidth, SlideHeight, DispWidth, DispHeight);
+}
+
+void Iris::prepare()
+{
+ static GLubyte img[3] = { 80, 80, 80 };
+
+ glGenTextures(1, &maTexture);
+ glBindTexture(GL_TEXTURE_2D, maTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+}
+
+void Iris::finish()
+{
+ glDeleteTextures(1, &maTexture);
+}
+
+void OGLTransitionImpl::makeOutsideCubeFaceToLeft()
+{
+ clear();
+ Primitive Slide;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,-1),90,false,0.0,1.0));
+
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ OverallOperations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,-1),-90,true,0.0,1.0));
+}
+
+void OGLTransitionImpl::makeInsideCubeFaceToLeft()
+{
+ clear();
+ Primitive Slide;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,1),-90,false,0.0,1.0));
+
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ OverallOperations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,1),90,true,0.0,1.0));
+}
+
+void OGLTransitionImpl::makeFallLeaving()
+{
+ clear();
+ Primitive Slide;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(1,0,0),basegfx::B3DVector(0,-1,0), 90,true,0.0,1.0));
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ mbUseMipMapEntering = false;
+}
+
+void OGLTransitionImpl::makeTurnAround()
+{
+ clear();
+ Primitive Slide;
+
+ mbReflectSlides = true;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,0),-180,false,0.0,1.0));
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ OverallOperations.push_back(new STranslate(basegfx::B3DVector(0, 0, -1.5),true, 0, 0.5));
+ OverallOperations.push_back(new STranslate(basegfx::B3DVector(0, 0, 1.5), true, 0.5, 1));
+ OverallOperations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0, 1, 0),basegfx::B3DVector(0, 0, 0), -180, true, 0.0, 1.0));
+}
+
+void OGLTransitionImpl::makeTurnDown()
+{
+ clear();
+ Primitive Slide;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.push_back(new STranslate(basegfx::B3DVector(0, 0, 0.0001), false, -1.0, 0.0));
+ Slide.Operations.push_back(new SRotate (basegfx::B3DVector(0, 0, 1), basegfx::B3DVector(-1, 1, 0), -90, true, 0.0, 1.0));
+ Slide.Operations.push_back(new SRotate (basegfx::B3DVector(0, 0, 1), basegfx::B3DVector(-1, 1, 0), 90, false, -1.0, 0.0));
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ mbUseMipMapLeaving = false;
+}
+
+void OGLTransitionImpl::makeIris()
+{
+ clear();
+ Primitive Slide;
+
+ Slide.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0,1));
+ Slide.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (0,1), basegfx::B2DVector (1,1));
+ maEnteringSlidePrimitives.push_back (Slide);
+
+ Slide.Operations.push_back (new STranslate (basegfx::B3DVector (0, 0, 0.000001), false, -1, 0));
+ Slide.Operations.push_back (new STranslate (basegfx::B3DVector (0, 0, -0.000002), false, 0.5, 1));
+ maLeavingSlidePrimitives.push_back (Slide);
+
+
+ Primitive irisPart, part;
+ int i, nSteps = 24, nParts = 7;
+ double lt = 0, t = 1.0/nSteps, cx, cy, lcx, lcy, lx = 1, ly = 0, x, y, cxo, cyo, lcxo, lcyo, of=2.2, f=1.42;
+
+ for (i=1; i<=nSteps; i++) {
+ x = cos ((3*2*M_PI*t)/nParts);
+ y = -sin ((3*2*M_PI*t)/nParts);
+ cx = (f*x + 1)/2;
+ cy = (f*y + 1)/2;
+ lcx = (f*lx + 1)/2;
+ lcy = (f*ly + 1)/2;
+ cxo = (of*x + 1)/2;
+ cyo = (of*y + 1)/2;
+ lcxo = (of*lx + 1)/2;
+ lcyo = (of*ly + 1)/2;
+ irisPart.pushTriangle (basegfx::B2DVector (lcx, lcy),
+ basegfx::B2DVector (lcxo, lcyo),
+ basegfx::B2DVector (cx, cy));
+ irisPart.pushTriangle (basegfx::B2DVector (cx, cy),
+ basegfx::B2DVector (lcxo, lcyo),
+ basegfx::B2DVector (cxo, cyo));
+ lx = x;
+ ly = y;
+ lt = t;
+ t += 1.0/nSteps;
+ }
+
+ Iris* pIris = new Iris();
+ double angle = 87;
+
+ for (i = 0; i < nParts; i++) {
+ irisPart.Operations.clear ();
+ double rx, ry;
+
+ rx = cos ((2*M_PI*i)/nParts);
+ ry = sin ((2*M_PI*i)/nParts);
+ irisPart.Operations.push_back (new SRotate (basegfx::B3DVector(0, 0, 1), basegfx::B3DVector(rx, ry, 0), angle, true, 0.0, 0.5));
+ irisPart.Operations.push_back (new SRotate (basegfx::B3DVector(0, 0, 1), basegfx::B3DVector(rx, ry, 0), -angle, true, 0.5, 1));
+ if (i > 0) {
+ irisPart.Operations.push_back (new STranslate (basegfx::B3DVector(rx, ry, 0), false, -1, 0));
+ irisPart.Operations.push_back (new SRotate (basegfx::B3DVector(0, 0, 1), basegfx::B3DVector(0, 0, 0), i*360.0/nParts, false, -1, 0));
+ irisPart.Operations.push_back (new STranslate (basegfx::B3DVector(-1, 0, 0), false, -1, 0));
+ }
+ irisPart.Operations.push_back(new STranslate(basegfx::B3DVector(0, 0, 1), false, -2, 0.0));
+ irisPart.Operations.push_back (new SRotate (basegfx::B3DVector(1, .5, 0), basegfx::B3DVector(1, 0, 0), -30, false, -1, 0));
+ pIris->pushPrimitive (irisPart);
+ }
+
+ maSceneObjects.push_back (pIris);
+
+ mbUseMipMapLeaving = mbUseMipMapEntering = false;
+}
+
+void OGLTransitionImpl::displaySlidesRochade( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex,
+ double SlideWidthScale, double SlideHeightScale )
+{
+ applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
+
+ glEnable(GL_TEXTURE_2D);
+
+ if( nTime > .5) {
+ displaySlide( nTime, glLeavingSlideTex, maLeavingSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ displaySlide( nTime, glEnteringSlideTex, maEnteringSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ } else {
+ displaySlide( nTime, glEnteringSlideTex, maEnteringSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ displaySlide( nTime, glLeavingSlideTex, maLeavingSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ }
+}
+
+void OGLTransitionImpl::makeRochade()
+{
+ clear();
+ Primitive Slide;
+
+ mbReflectSlides = true;
+ mmDisplaySlides = &OGLTransitionImpl::displaySlidesRochade;
+
+ double w, h;
+
+ w = 2.2;
+ h = 10;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+
+ Slide.Operations.push_back(new SEllipseTranslate(w, h, 0.25, -0.25, true, 0, 1));
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,0), -45, true, 0, 1));
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.clear();
+ Slide.Operations.push_back(new SEllipseTranslate(w, h, 0.75, 0.25, true, 0, 1));
+ Slide.Operations.push_back(new STranslate(basegfx::B3DVector(0, 0, -h), false, -1, 0));
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,0), -45, true, 0, 1));
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0,1,0),basegfx::B3DVector(0,0,0), 45, false, -1, 0));
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ // OverallOperations.push_back(new SEllipseTranslate(0.5, 2, 0, 1, true, 0, 1));
+// push_back(new STranslate(basegfx::B3DVector(0, 0, -2), true, 0, 0.5));
+// OverallOperations.push_back(new STranslate(basegfx::B3DVector(0, 0, 2), true, 0.5, 1));
+}
+
+// TODO(Q3): extract to basegfx
+inline basegfx::B2DVector clamp(const basegfx::B2DVector& v)
+{
+ return basegfx::B2DVector(min(max(v.getX(),-1.0),1.0),
+ min(max(v.getY(),-1.0),1.0));
+}
+
+// TODO(Q3): extract to basegfx
+inline basegfx::B3DVector clamp(const basegfx::B3DVector& v)
+{
+ return basegfx::B3DVector(min(max(v.getX(),-1.0),1.0),
+ min(max(v.getY(),-1.0),1.0),
+ min(max(v.getZ(),-1.0),1.0));
+}
+
+inline double randFromNeg1to1()
+{
+ return ( ( static_cast<double>( rand() ) / static_cast<double>( RAND_MAX ) ) * 2.0 ) - 1.0;
+}
+
+// TODO(Q3): extract to basegfx
+inline basegfx::B3DVector randNormVectorInXYPlane()
+{
+ basegfx::B3DVector toReturn(randFromNeg1to1(),randFromNeg1to1(),0.0);
+ return toReturn/toReturn.getLength();
+}
+
+void OGLTransitionImpl::makeRevolvingCircles( ::sal_uInt16 nCircles , ::sal_uInt16 nPointsOnCircles )
+{
+ clear();
+ double dAngle(2*3.1415926/static_cast<double>( nPointsOnCircles ));
+ if(nCircles < 2 || nPointsOnCircles < 4)
+ {
+ makeNByMTileFlip(1,1);
+ return;
+ }
+ double Radius(1.0/static_cast<double>( nCircles ));
+ double dRadius(Radius);
+ double LastRadius(0.0);
+ double NextRadius(2*Radius);
+
+ /// now we know there is at least two circles
+ /// the first will always be a full circle
+ /// the last will always be the outer shell of the slide with a circle hole
+
+ //add the full circle
+ vector<basegfx::B2DVector> unScaledTexCoords;
+ double TempAngle(0.0);
+ for(unsigned int Point(0); Point < nPointsOnCircles; ++Point)
+ {
+ unScaledTexCoords.push_back( basegfx::B2DVector( cos(TempAngle - 3.1415926/2.0) , sin(TempAngle- 3.1415926/2.0) ) );
+
+ TempAngle += dAngle;
+ }
+
+ {
+ //double angle(0.0);
+ Primitive EnteringSlide;
+ Primitive LeavingSlide;
+ for(int Point(0); Point + 1 < nPointsOnCircles; ++Point)
+ {
+ EnteringSlide.pushTriangle( basegfx::B2DVector( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0 + basegfx::B2DVector( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0 + basegfx::B2DVector( 0.5 , 0.5 ) );
+ LeavingSlide.pushTriangle( basegfx::B2DVector( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point + 1 ] / 2.0 + basegfx::B2DVector( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ Point ] / 2.0 + basegfx::B2DVector( 0.5, 0.5) );
+ }
+ EnteringSlide.pushTriangle( basegfx::B2DVector(0.5,0.5) , Radius * unScaledTexCoords[ 0 ] / 2.0 + basegfx::B2DVector( 0.5 , 0.5 ) , Radius * unScaledTexCoords[ nPointsOnCircles - 1 ] / 2.0 + basegfx::B2DVector( 0.5 , 0.5 ) );
+ LeavingSlide.pushTriangle( basegfx::B2DVector(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) , Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ basegfx::B3DVector axis(randNormVectorInXYPlane());
+ EnteringSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
+ LeavingSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
+ EnteringSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , -180, false,0.0,1.0) );
+
+ maEnteringSlidePrimitives.push_back(EnteringSlide);
+ maLeavingSlidePrimitives.push_back(LeavingSlide);
+ LastRadius = Radius;
+ Radius = NextRadius;
+ NextRadius += dRadius;
+ }
+
+ for(int i(1); i < nCircles - 1; ++i)
+ {
+ Primitive LeavingSlide;
+ Primitive EnteringSlide;
+ for(int Side(0); Side < nPointsOnCircles - 1; ++Side)
+ {
+ EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ EnteringSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ LeavingSlide.pushTriangle(Radius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) , Radius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ }
+
+ EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ EnteringSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ LeavingSlide.pushTriangle(Radius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) , Radius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ basegfx::B3DVector axis(randNormVectorInXYPlane());
+ EnteringSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
+ LeavingSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , 180, true, Radius/2.0 , (NextRadius + 1)/2.0 ) );
+ EnteringSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , -180, false,0.0,1.0) );
+
+ maEnteringSlidePrimitives.push_back(EnteringSlide);
+ maLeavingSlidePrimitives.push_back(LeavingSlide);
+
+ LastRadius = Radius;
+ Radius = NextRadius;
+ NextRadius += dRadius;
+ }
+ {
+ Radius = sqrt(2.0);
+ Primitive LeavingSlide;
+ Primitive EnteringSlide;
+ for(int Side(0); Side < nPointsOnCircles - 1; ++Side)
+ {
+
+ EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[Side])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[Side + 1]/2.0 + basegfx::B2DVector(0.5,0.5) , clamp(Radius*unScaledTexCoords[Side + 1])/2.0 + basegfx::B2DVector(0.5,0.5) );
+ }
+
+ EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ EnteringSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[nPointsOnCircles - 1]/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) );
+ LeavingSlide.pushTriangle(clamp(Radius*unScaledTexCoords[nPointsOnCircles - 1])/2.0 + basegfx::B2DVector(0.5,0.5) , LastRadius*unScaledTexCoords[0]/2.0 + basegfx::B2DVector(0.5,0.5) , clamp(Radius*unScaledTexCoords[0])/2.0 + basegfx::B2DVector(0.5,0.5) );
+
+ basegfx::B3DVector axis(randNormVectorInXYPlane());
+ EnteringSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) );
+ LeavingSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , 180, true, (LastRadius + dRadius)/2.0 , 1.0 ) );
+ EnteringSlide.Operations.push_back( new SRotate( axis , basegfx::B3DVector(0,0,0) , -180, false,0.0,1.0) );
+
+ maEnteringSlidePrimitives.push_back(EnteringSlide);
+ maLeavingSlidePrimitives.push_back(LeavingSlide);
+ }
+}
+
+void OGLTransitionImpl::makeHelix( ::sal_uInt16 nRows )
+{
+ clear();
+ double invN(1.0/static_cast<double>(nRows));
+ double iDn = 0.0;
+ double iPDn = invN;
+ for(unsigned int i(0); i < nRows; ++i)
+ {
+ Primitive Tile;
+
+ Tile.pushTriangle(basegfx::B2DVector( 1.0 , iDn ) , basegfx::B2DVector( 0.0 , iDn ) , basegfx::B2DVector( 0.0 , iPDn ));
+
+ Tile.pushTriangle(basegfx::B2DVector( 1.0 , iPDn ) , basegfx::B2DVector( 1.0 , iDn ) , basegfx::B2DVector( 0.0 , iPDn ));
+
+ Tile.Operations.push_back( new SRotate( basegfx::B3DVector( 0 , 1 , 0 ) , ( Tile.getVertices()[1] + Tile.getVertices()[3] )/2.0 , 180 ,
+ true,min(max(static_cast<double>(i - nRows/2.0)*invN/2.0,0.0),1.0),
+ min(max(static_cast<double>(i + nRows/2.0)*invN/2.0,0.0),1.0) ) );
+
+ maLeavingSlidePrimitives.push_back(Tile);
+
+ Tile.Operations.push_back( new SRotate( basegfx::B3DVector( 0 , 1 , 0 ) , ( Tile.getVertices()[1] + Tile.getVertices()[3] )/2.0 , -180 , false,0.0,1.0) );
+
+ maEnteringSlidePrimitives.push_back(Tile);
+
+ iDn += invN;
+ iPDn += invN;
+ }
+}
+
+void OGLTransitionImpl::makeNByMTileFlip( ::sal_uInt16 n, ::sal_uInt16 m )
+{
+ clear();
+ double invN(1.0/static_cast<double>(n));
+ double invM(1.0/static_cast<double>(m));
+ double iDn = 0.0;
+ double iPDn = invN;
+ for(unsigned int i(0); i < n; ++i)
+ {
+ double jDm = 0.0;
+ double jPDm = invM;
+ for(unsigned int j(0); j < m; ++j)
+ {
+ Primitive Tile;
+
+ Tile.pushTriangle(basegfx::B2DVector( iPDn , jDm ) , basegfx::B2DVector( iDn , jDm ) , basegfx::B2DVector( iDn , jPDm ));
+
+ Tile.pushTriangle(basegfx::B2DVector( iPDn , jPDm ) , basegfx::B2DVector( iPDn , jDm ) , basegfx::B2DVector( iDn , jPDm ));//bottom left corner of tile
+
+ Tile.Operations.push_back( new SRotate( basegfx::B3DVector( 1 , 1 , 0 ) , ( Tile.getVertices()[1] + Tile.getVertices()[3] )/2.0 , 180 , true, iDn*jDm/2.0 , ((iPDn*jPDm)+1.0)/2.0 ) );
+ maLeavingSlidePrimitives.push_back(Tile);
+ Tile.Operations.push_back( new SRotate( basegfx::B3DVector( 1 , 1 , 0 ) , ( Tile.getVertices()[1] + Tile.getVertices()[3] )/2.0 , -180, false, iDn*jDm/2.0 , ((iPDn*jPDm)+1.0)/2.0 ) );
+
+ maEnteringSlidePrimitives.push_back(Tile);
+
+ jDm += invM;
+ jPDm += invM;
+ }
+ iDn += invN;
+ iPDn += invN;
+ }
+}
+
+SRotate::SRotate(const basegfx::B3DVector& Axis,const basegfx::B3DVector& Origin,double Angle, bool bInter, double T0, double T1):axis(Axis),origin(Origin),angle(Angle)
+{
+ nT0 = T0;
+ nT1 = T1;
+ bInterpolate = bInter;
+}
+
+SScale::SScale(const basegfx::B3DVector& Scale,const basegfx::B3DVector& Origin, bool bInter, double T0, double T1):scale(Scale),origin(Origin)
+{
+ nT0 = T0;
+ nT1 = T1;
+ bInterpolate = bInter;
+}
+
+RotateAndScaleDepthByWidth::RotateAndScaleDepthByWidth(const basegfx::B3DVector& Axis,const basegfx::B3DVector& Origin,double Angle, bool bInter, double T0, double T1):axis(Axis),origin(Origin),angle(Angle)
+{
+ nT0 = T0;
+ nT1 = T1;
+ bInterpolate = bInter;
+}
+
+RotateAndScaleDepthByHeight::RotateAndScaleDepthByHeight(const basegfx::B3DVector& Axis,const basegfx::B3DVector& Origin,double Angle, bool bInter, double T0, double T1):axis(Axis),origin(Origin),angle(Angle)
+{
+ nT0 = T0;
+ nT1 = T1;
+ bInterpolate = bInter;
+}
+
+
+STranslate::STranslate(const basegfx::B3DVector& Vector, bool bInter, double T0, double T1):vector(Vector)
+{
+ nT0 = T0;
+ nT1 = T1;
+ bInterpolate = bInter;
+}
+
+inline double intervalInter(double t, double T0, double T1)
+{
+ return ( t - T0 ) / ( T1 - T0 );
+}
+
+void STranslate::interpolate(double t,double SlideWidthScale,double SlideHeightScale)
+{
+ if(t <= nT0)
+ return;
+ if(!bInterpolate || t > nT1)
+ t = nT1;
+ t = intervalInter(t,nT0,nT1);
+ glTranslated(SlideWidthScale*t*vector.getX(),SlideHeightScale*t*vector.getY(),t*vector.getZ());
+}
+
+void SRotate::interpolate(double t,double SlideWidthScale,double SlideHeightScale)
+{
+ if(t <= nT0)
+ return;
+ if(!bInterpolate || t > nT1)
+ t = nT1;
+ t = intervalInter(t,nT0,nT1);
+ glTranslated(SlideWidthScale*origin.getX(),SlideHeightScale*origin.getY(),origin.getZ());
+ glScaled(SlideWidthScale,SlideHeightScale,1);
+ glRotated(t*angle,axis.getX(),axis.getY(),axis.getZ());
+ glScaled(1/SlideWidthScale,1/SlideHeightScale,1);
+ glTranslated(-SlideWidthScale*origin.getX(),-SlideHeightScale*origin.getY(),-origin.getZ());
+}
+
+void SScale::interpolate(double t,double SlideWidthScale,double SlideHeightScale)
+{
+ if(t <= nT0)
+ return;
+ if(!bInterpolate || t > nT1)
+ t = nT1;
+ t = intervalInter(t,nT0,nT1);
+ glTranslated(SlideWidthScale*origin.getX(),SlideHeightScale*origin.getY(),origin.getZ());
+ glScaled((1-t) + t*scale.getX(),(1-t) + t*scale.getY(),(1-t) + t*scale.getZ());
+ glTranslated(-SlideWidthScale*origin.getX(),-SlideHeightScale*origin.getY(),-origin.getZ());
+}
+
+void RotateAndScaleDepthByWidth::interpolate(double t,double SlideWidthScale,double SlideHeightScale)
+{
+ if(t <= nT0)
+ return;
+ if(!bInterpolate || t > nT1)
+ t = nT1;
+ t = intervalInter(t,nT0,nT1);
+ glTranslated(SlideWidthScale*origin.getX(),SlideHeightScale*origin.getY(),SlideWidthScale*origin.getZ());
+ glRotated(t*angle,axis.getX(),axis.getY(),axis.getZ());
+ glTranslated(-SlideWidthScale*origin.getX(),-SlideHeightScale*origin.getY(),-SlideWidthScale*origin.getZ());
+}
+
+void RotateAndScaleDepthByHeight::interpolate(double t,double SlideWidthScale,double SlideHeightScale)
+{
+ if(t <= nT0)
+ return;
+ if(!bInterpolate || t > nT1)
+ t = nT1;
+ t = intervalInter(t,nT0,nT1);
+ glTranslated(SlideWidthScale*origin.getX(),SlideHeightScale*origin.getY(),SlideHeightScale*origin.getZ());
+ glRotated(t*angle,axis.getX(),axis.getY(),axis.getZ());
+ glTranslated(-SlideWidthScale*origin.getX(),-SlideHeightScale*origin.getY(),-SlideHeightScale*origin.getZ());
+}
+
+SEllipseTranslate::SEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1)
+{
+ nT0 = T0;
+ nT1 = T1;
+ bInterpolate = bInter;
+ width = dWidth;
+ height = dHeight;
+ startPosition = dStartPosition;
+ endPosition = dEndPosition;
+}
+
+void SEllipseTranslate::interpolate(double t,double /* SlideWidthScale */,double /* SlideHeightScale */)
+{
+ if(t <= nT0)
+ return;
+ if(!bInterpolate || t > nT1)
+ t = nT1;
+ t = intervalInter(t,nT0,nT1);
+
+ double a1, a2, x, y;
+ a1 = startPosition*2*M_PI;
+ a2 = (startPosition + t*(endPosition - startPosition))*2*M_PI;
+ x = width*(cos (a2) - cos (a1))/2;
+ y = height*(sin (a2) - sin (a1))/2;
+
+ glTranslated(x, 0, y);
+}
+
+STranslate* STranslate::clone()
+{
+ return new STranslate(*this);
+}
+SRotate* SRotate::clone()
+{
+ return new SRotate(*this);
+}
+
+SScale* SScale::clone()
+{
+ return new SScale(*this);
+}
+
+SEllipseTranslate* SEllipseTranslate::clone()
+{
+ return new SEllipseTranslate(*this);
+}
+
+RotateAndScaleDepthByWidth* RotateAndScaleDepthByWidth::clone()
+{
+ return new RotateAndScaleDepthByWidth(*this);
+}
+
+RotateAndScaleDepthByHeight* RotateAndScaleDepthByHeight::clone()
+{
+ return new RotateAndScaleDepthByHeight(*this);
+}
+
+const Primitive& Primitive::operator=(const Primitive& rvalue)
+{
+ for(unsigned int i( 0 ); i < rvalue.Operations.size(); ++i)
+ Operations.push_back(rvalue.Operations[i]->clone());
+ for(unsigned int i( 0 ); i < rvalue.Vertices.size(); ++i)//SPEED! use copy or something. this is slow.
+ Vertices.push_back(rvalue.Vertices[i]);
+ for(unsigned int i( 0 ); i < rvalue.TexCoords.size(); ++i)//SPEED! use copy or something. this is slow.
+ TexCoords.push_back(rvalue.TexCoords[i]);
+ for(unsigned int i( 0 ); i < rvalue.Normals.size(); ++i)//SPEED! use copy or something. this is slow.
+ Normals.push_back(rvalue.Normals[i]);
+ return *this;
+}
+
+Primitive::Primitive(const Primitive& rvalue)
+{
+ for(unsigned int i( 0 ); i < rvalue.Operations.size(); ++i)
+ Operations.push_back(rvalue.Operations[i]->clone());
+ for(unsigned int i( 0 ); i < rvalue.Vertices.size(); ++i)//SPEED! use copy or something. this is slow.
+ Vertices.push_back(rvalue.Vertices[i]);
+ for(unsigned int i( 0 ); i < rvalue.TexCoords.size(); ++i)//SPEED! use copy or something. this is slow.
+ TexCoords.push_back(rvalue.TexCoords[i]);
+ for(unsigned int i( 0 ); i < rvalue.Normals.size(); ++i)//SPEED! use copy or something. this is slow.
+ Normals.push_back(rvalue.Normals[i]);
+}
+
+void Primitive::pushTriangle(const basegfx::B2DVector& SlideLocation0,const basegfx::B2DVector& SlideLocation1,const basegfx::B2DVector& SlideLocation2)
+{
+ vector<basegfx::B3DVector> Verts;
+ vector<basegfx::B2DVector> Texs;
+ Verts.reserve(3);
+ Texs.reserve(3);
+
+ Verts.push_back(basegfx::B3DVector( 2*SlideLocation0.getX() - 1, -2*SlideLocation0.getY() + 1 , 0.0 ));
+ Verts.push_back(basegfx::B3DVector( 2*SlideLocation1.getX() - 1, -2*SlideLocation1.getY() + 1 , 0.0 ));
+ Verts.push_back(basegfx::B3DVector( 2*SlideLocation2.getX() - 1, -2*SlideLocation2.getY() + 1 , 0.0 ));
+
+ //figure out if they're facing the correct way, and make them face the correct way.
+ basegfx::B3DVector Normal( basegfx::cross( Verts[0] - Verts[1] , Verts[1] - Verts[2] ) );
+ if(Normal.getZ() >= 0.0)//if the normal is facing us
+ {
+ Texs.push_back(SlideLocation0);
+ Texs.push_back(SlideLocation1);
+ Texs.push_back(SlideLocation2);
+ }
+ else // if the normal is facing away from us, make it face us
+ {
+ Texs.push_back(SlideLocation0);
+ Texs.push_back(SlideLocation2);
+ Texs.push_back(SlideLocation1);
+ Verts.clear();
+ Verts.push_back(basegfx::B3DVector( 2*SlideLocation0.getX() - 1, -2*SlideLocation0.getY() + 1 , 0.0 ));
+ Verts.push_back(basegfx::B3DVector( 2*SlideLocation2.getX() - 1, -2*SlideLocation2.getY() + 1 , 0.0 ));
+ Verts.push_back(basegfx::B3DVector( 2*SlideLocation1.getX() - 1, -2*SlideLocation1.getY() + 1 , 0.0 ));
+ }
+
+ Vertices.push_back(Verts[0]);
+ Vertices.push_back(Verts[1]);
+ Vertices.push_back(Verts[2]);
+
+ TexCoords.push_back(Texs[0]);
+ TexCoords.push_back(Texs[1]);
+ TexCoords.push_back(Texs[2]);
+
+ Normals.push_back(basegfx::B3DVector(0,0,1));//all normals always face the screen when untransformed.
+ Normals.push_back(basegfx::B3DVector(0,0,1));//all normals always face the screen when untransformed.
+ Normals.push_back(basegfx::B3DVector(0,0,1));//all normals always face the screen when untransformed.
+}
+
+void OGLTransitionImpl::makeDiamond()
+{
+ mmPrepare = &OGLTransitionImpl::prepareDiamond;
+ mbUseMipMapLeaving = mbUseMipMapEntering = false;
+}
+
+void OGLTransitionImpl::prepareDiamond( double nTime, double /* SlideWidth */, double /* SlideHeight */, double /* DispWidth */, double /* DispHeight */ )
+{
+ Primitive Slide1, Slide2;
+
+ Slide1.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0,1));
+ Slide1.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (0,1), basegfx::B2DVector (1,1));
+ maEnteringSlidePrimitives.push_back (Slide1);
+
+
+ if( nTime >= 0.5 ) {
+ double m = 1 - nTime;
+
+ Slide2.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (m,0), basegfx::B2DVector (0,m));
+ Slide2.pushTriangle (basegfx::B2DVector (nTime,0), basegfx::B2DVector (1,0), basegfx::B2DVector (1,m));
+ Slide2.pushTriangle (basegfx::B2DVector (1,nTime), basegfx::B2DVector (1,1), basegfx::B2DVector (nTime,1));
+ Slide2.pushTriangle (basegfx::B2DVector (0,nTime), basegfx::B2DVector (m,1), basegfx::B2DVector (0,1));
+ } else {
+ double l = 0.5 - nTime;
+ double h = 0.5 + nTime;
+
+ Slide2.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0.5,l));
+ Slide2.pushTriangle (basegfx::B2DVector (0.5,l), basegfx::B2DVector (1,0), basegfx::B2DVector (h,0.5));
+ Slide2.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (1,1), basegfx::B2DVector (h,0.5));
+ Slide2.pushTriangle (basegfx::B2DVector (h,0.5), basegfx::B2DVector (1,1), basegfx::B2DVector (0.5,h));
+ Slide2.pushTriangle (basegfx::B2DVector (0.5,h), basegfx::B2DVector (1,1), basegfx::B2DVector (0,1));
+ Slide2.pushTriangle (basegfx::B2DVector (l,0.5), basegfx::B2DVector (0.5,h), basegfx::B2DVector (0,1));
+ Slide2.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (l,0.5), basegfx::B2DVector (0,1));
+ Slide2.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (0.5,l), basegfx::B2DVector (l,0.5));
+ }
+ Slide2.Operations.push_back (new STranslate (basegfx::B3DVector (0, 0, 0.00000001), false, -1, 0));
+ maLeavingSlidePrimitives.push_back (Slide2);
+}
+
+void OGLTransitionImpl::makeVenetianBlinds( bool vertical, int parts )
+{
+ static double t30 = tan( M_PI/6.0 );
+ double n, ln = 0;
+ double p = 1.0/parts;
+
+ for( int i=0; i<parts; i++ ) {
+ Primitive Slide;
+ n = (i + 1)/(double)parts;
+ if( vertical ) {
+ Slide.pushTriangle (basegfx::B2DVector (ln,0), basegfx::B2DVector (n,0), basegfx::B2DVector (ln,1));
+ Slide.pushTriangle (basegfx::B2DVector (n,0), basegfx::B2DVector (ln,1), basegfx::B2DVector (n,1));
+ Slide.Operations.push_back(new RotateAndScaleDepthByWidth(basegfx::B3DVector(0, 1, 0), basegfx::B3DVector(n + ln - 1, 0, -t30*p), -120, true, 0.0, 1.0));
+ } else {
+ Slide.pushTriangle (basegfx::B2DVector (0,ln), basegfx::B2DVector (1,ln), basegfx::B2DVector (0,n));
+ Slide.pushTriangle (basegfx::B2DVector (1,ln), basegfx::B2DVector (0,n), basegfx::B2DVector (1,n));
+ Slide.Operations.push_back(new RotateAndScaleDepthByHeight(basegfx::B3DVector(1, 0, 0), basegfx::B3DVector(0, 1 - n - ln, -t30*p), -120, true, 0.0, 1.0));
+ }
+ maLeavingSlidePrimitives.push_back (Slide);
+
+ if( vertical ) {
+ Slide.Operations.push_back(new SRotate(basegfx::B3DVector(0, 1, 0), basegfx::B3DVector(2*n - 1, 0, 0), -60, false, -1, 0));
+ Slide.Operations.push_back(new SRotate(basegfx::B3DVector(0, 1, 0), basegfx::B3DVector(n + ln - 1, 0, 0), 180, false, -1, 0));
+ } else {
+ Slide.Operations.push_back(new SRotate(basegfx::B3DVector(1, 0, 0), basegfx::B3DVector(0, 1 - 2*n, 0), -60, false, -1, 0));
+ Slide.Operations.push_back(new SRotate(basegfx::B3DVector(1, 0, 0), basegfx::B3DVector(0, 1 - n - ln, 0), 180, false, -1, 0));
+ }
+ maEnteringSlidePrimitives.push_back (Slide);
+ ln = n;
+ }
+}
+
+void OGLTransitionImpl::displaySlidesFadeSmoothly( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale )
+{
+ applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
+
+ glDisable(GL_DEPTH_TEST);
+
+ displaySlide( nTime, glLeavingSlideTex, maLeavingSlidePrimitives, SlideWidthScale, SlideHeightScale );
+
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glColor4f( 1, 1, 1, nTime );
+ displaySlide( nTime, glEnteringSlideTex, maEnteringSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ glDisable(GL_BLEND);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glEnable(GL_LIGHTING);
+
+ glEnable(GL_DEPTH_TEST);
+}
+
+void OGLTransitionImpl::makeFadeSmoothly()
+{
+ Primitive Slide;
+
+ Slide.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0,1));
+ Slide.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (0,1), basegfx::B2DVector (1,1));
+ maLeavingSlidePrimitives.push_back (Slide);
+ maEnteringSlidePrimitives.push_back (Slide);
+
+ mmDisplaySlides = &OGLTransitionImpl::displaySlidesFadeSmoothly;
+ mbUseMipMapLeaving = mbUseMipMapEntering = false;
+}
+
+void OGLTransitionImpl::displaySlidesFadeThroughBlack( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale )
+{
+ applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
+
+ glDisable(GL_DEPTH_TEST);
+
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ if( nTime < 0.5 ) {
+ glColor4f( 1, 1, 1, 1 - nTime*2 );
+ displaySlide( nTime, glLeavingSlideTex, maLeavingSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ } else {
+ glColor4f( 1, 1, 1, (nTime - 0.5)*2 );
+ displaySlide( nTime, glEnteringSlideTex, maEnteringSlidePrimitives, SlideWidthScale, SlideHeightScale );
+ }
+ glDisable(GL_BLEND);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glEnable(GL_LIGHTING);
+
+ glEnable(GL_DEPTH_TEST);
+}
+
+void OGLTransitionImpl::makeFadeThroughBlack()
+{
+ Primitive Slide;
+
+ Slide.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0,1));
+ Slide.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (0,1), basegfx::B2DVector (1,1));
+ maLeavingSlidePrimitives.push_back (Slide);
+ maEnteringSlidePrimitives.push_back (Slide);
+
+ mmDisplaySlides = &OGLTransitionImpl::displaySlidesFadeThroughBlack;
+ mbUseMipMapLeaving = mbUseMipMapEntering = false;
+}
+
+static const char* basicVertexShader = "\n\
+varying vec2 v_texturePosition;\n\
+\n\
+void main( void )\n\
+{\n\
+ gl_Position = ftransform();\n\
+ v_texturePosition = gl_MultiTexCoord0.xy;\n\
+}\n\
+";
+
+static const char* staticFragmentShader = "\n\
+uniform sampler2D leavingSlideTexture;\n\
+uniform sampler2D enteringSlideTexture;\n\
+uniform sampler2D permTexture;\n\
+uniform float time;\n\
+varying vec2 v_texturePosition;\n\
+\n\
+float snoise(vec2 P) {\n\
+\n\
+ return texture2D(permTexture, P).r;\n\
+}\n\
+\n\
+\n\
+#define PART 0.5\n\
+#define START 0.4\n\
+#define END 0.9\n\
+\n\
+void main() {\n\
+ float sn = snoise(10.0*v_texturePosition+time*0.07);\n\
+ if( time < PART ) {\n\
+ float sn1 = snoise(vec2(time*15.0, 20.0*v_texturePosition.y));\n\
+ float sn2 = snoise(v_texturePosition);\n\
+ if (sn1 > 1.0 - time*time && sn2 < 2.0*time+0.1)\n\
+ gl_FragColor = vec4(sn, sn, sn, 1.0);\n\
+ else if (time > START )\n\
+ gl_FragColor = ((time-START)/(PART - START))*vec4(sn, sn, sn, 1.0) + (1.0 - (time - START)/(PART - START))*texture2D(leavingSlideTexture, v_texturePosition);\n\
+ else\n\
+ gl_FragColor = texture2D(leavingSlideTexture, v_texturePosition);\n\
+ } else if ( time < PART ) {\n\
+ gl_FragColor = texture2D(leavingSlideTexture, v_texturePosition);\n\
+ } else if ( time > END ) {\n\
+ gl_FragColor = ((1.0 - time)/(1.0 - END))*vec4(sn, sn, sn, 1.0) + ((time - END)/(1.0 - END))*texture2D(enteringSlideTexture, v_texturePosition);\n\
+ } else \n\
+ gl_FragColor = vec4(sn, sn, sn, 1.0);\n\
+}\n\
+";
+
+static const char* dissolveFragmentShader = "\n\
+uniform sampler2D leavingSlideTexture;\n\
+uniform sampler2D enteringSlideTexture;\n\
+uniform sampler2D permTexture;\n\
+uniform float time;\n\
+varying vec2 v_texturePosition;\n\
+\n\
+float snoise(vec2 P) {\n\
+\n\
+ return texture2D(permTexture, P).r;\n\
+}\n\
+\n\
+void main() {\n\
+ float sn = snoise(10.0*v_texturePosition);\n\
+ if( sn < time)\n\
+ gl_FragColor = texture2D(enteringSlideTexture, v_texturePosition);\n\
+ else\n\
+ gl_FragColor = texture2D(leavingSlideTexture, v_texturePosition);\n\
+}\n\
+";
+
+int permutation256 [256]= {
+215, 100, 200, 204, 233, 50, 85, 196,
+ 71, 141, 122, 160, 93, 131, 243, 234,
+162, 183, 36, 155, 4, 62, 35, 205,
+ 40, 102, 33, 27, 255, 55, 214, 156,
+ 75, 163, 134, 126, 249, 74, 197, 228,
+ 72, 90, 206, 235, 17, 22, 49, 169,
+227, 89, 16, 5, 117, 60, 248, 230,
+217, 68, 138, 96, 194, 170, 136, 10,
+112, 238, 184, 189, 176, 42, 225, 212,
+ 84, 58, 175, 244, 150, 168, 219, 236,
+101, 208, 123, 37, 164, 110, 158, 201,
+ 78, 114, 57, 48, 70, 142, 106, 43,
+232, 26, 32, 252, 239, 98, 191, 94,
+ 59, 149, 39, 187, 203, 190, 19, 13,
+133, 45, 61, 247, 23, 34, 20, 52,
+118, 209, 146, 193, 222, 18, 1, 152,
+ 46, 41, 91, 148, 115, 25, 135, 77,
+254, 147, 224, 161, 9, 213, 223, 250,
+231, 251, 127, 166, 63, 179, 81, 130,
+139, 28, 120, 151, 241, 86, 111, 0,
+ 88, 153, 172, 182, 159, 105, 178, 47,
+ 51, 167, 65, 66, 92, 73, 198, 211,
+245, 195, 31, 220, 140, 76, 221, 186,
+154, 185, 56, 83, 38, 165, 109, 67,
+124, 226, 132, 53, 229, 29, 12, 181,
+121, 24, 207, 199, 177, 113, 30, 80,
+ 3, 97, 188, 79, 216, 173, 8, 145,
+ 87, 128, 180, 237, 240, 137, 125, 104,
+ 15, 242, 119, 246, 103, 143, 95, 144,
+ 2, 44, 69, 157, 192, 174, 14, 54,
+218, 82, 64, 210, 11, 6, 129, 21,
+116, 171, 99, 202, 7, 107, 253, 108
+};
+
+void initPermTexture(GLuint *texID)
+{
+ glGenTextures(1, texID);
+ glBindTexture(GL_TEXTURE_2D, *texID);
+
+ static bool initialized = false;
+ static unsigned char permutation2D[256*256*4];
+ if( !initialized ) {
+ int x, y;
+
+ for( y=0; y < 256; y++ )
+ for( x=0; x < 256; x++ )
+ permutation2D[x*4 + y*1024] = permutation256[(y + permutation256[x]) & 0xff];
+
+ initialized = true;
+ }
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, permutation2D );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+}
+
+void OGLTransitionImpl::preparePermShader()
+{
+#ifdef GL_VERSION_2_0
+ if( mProgramObject ) {
+ OGLShaders::glUseProgram( mProgramObject );
+
+ GLint location = OGLShaders::glGetUniformLocation( mProgramObject, "leavingSlideTexture" );
+ if( location != -1 ) {
+ OGLShaders::glUniform1i( location, 0 ); // texture unit 0
+ }
+
+ glActiveTexture(GL_TEXTURE1);
+ if( !maHelperTexture )
+ initPermTexture( &maHelperTexture );
+ glActiveTexture(GL_TEXTURE0);
+
+ location = OGLShaders::glGetUniformLocation( mProgramObject, "permTexture" );
+ if( location != -1 ) {
+ OGLShaders::glUniform1i( location, 1 ); // texture unit 1
+ }
+
+ location = OGLShaders::glGetUniformLocation( mProgramObject, "enteringSlideTexture" );
+ if( location != -1 ) {
+ OGLShaders::glUniform1i( location, 2 ); // texture unit 2
+ }
+ }
+#endif
+}
+
+void OGLTransitionImpl::prepareStatic( ::sal_Int32 /* glLeavingSlideTex */, ::sal_Int32 /* glEnteringSlideTex */ )
+{
+ mProgramObject = OGLShaders::LinkProgram( basicVertexShader, staticFragmentShader );
+
+ preparePermShader();
+}
+
+void OGLTransitionImpl::displaySlidesShaders( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex,
+ double SlideWidthScale, double SlideHeightScale )
+{
+ applyOverallOperations( nTime, SlideWidthScale, SlideHeightScale );
+
+#ifdef GL_VERSION_2_0
+ if( mProgramObject ) {
+ GLint location = OGLShaders::glGetUniformLocation( mProgramObject, "time" );
+ if( location != -1 ) {
+ OGLShaders::glUniform1f( location, nTime );
+ }
+ }
+
+ glActiveTexture( GL_TEXTURE2 );
+ glBindTexture( GL_TEXTURE_2D, glEnteringSlideTex );
+ glActiveTexture( GL_TEXTURE0 );
+#endif
+
+ displaySlide( nTime, glLeavingSlideTex, maLeavingSlidePrimitives, SlideWidthScale, SlideHeightScale );
+}
+
+void OGLTransitionImpl::makeStatic()
+{
+ Primitive Slide;
+
+ Slide.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0,1));
+ Slide.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (0,1), basegfx::B2DVector (1,1));
+ maLeavingSlidePrimitives.push_back (Slide);
+ maEnteringSlidePrimitives.push_back (Slide);
+
+ mmDisplaySlides = &OGLTransitionImpl::displaySlidesShaders;
+ mmPrepareTransition = &OGLTransitionImpl::prepareStatic;
+ mbUseMipMapLeaving = mbUseMipMapEntering = false;
+
+ mnRequiredGLVersion = 2.0;
+}
+
+void OGLTransitionImpl::prepareDissolve( ::sal_Int32 /* glLeavingSlideTex */, ::sal_Int32 /* glEnteringSlideTex */ )
+{
+ mProgramObject = OGLShaders::LinkProgram( basicVertexShader, dissolveFragmentShader );
+
+ preparePermShader();
+}
+
+void OGLTransitionImpl::makeDissolve()
+{
+ Primitive Slide;
+
+ Slide.pushTriangle (basegfx::B2DVector (0,0), basegfx::B2DVector (1,0), basegfx::B2DVector (0,1));
+ Slide.pushTriangle (basegfx::B2DVector (1,0), basegfx::B2DVector (0,1), basegfx::B2DVector (1,1));
+ maLeavingSlidePrimitives.push_back (Slide);
+ maEnteringSlidePrimitives.push_back (Slide);
+
+ mmDisplaySlides = &OGLTransitionImpl::displaySlidesShaders;
+ mmPrepareTransition = &OGLTransitionImpl::prepareDissolve;
+ mbUseMipMapLeaving = mbUseMipMapEntering = false;
+
+ mnRequiredGLVersion = 2.0;
+}
+
+void OGLTransitionImpl::makeNewsflash()
+{
+ Primitive Slide;
+
+ Slide.pushTriangle(basegfx::B2DVector(0,0),basegfx::B2DVector(1,0),basegfx::B2DVector(0,1));
+ Slide.pushTriangle(basegfx::B2DVector(1,0),basegfx::B2DVector(0,1),basegfx::B2DVector(1,1));
+ Slide.Operations.push_back(new SRotate(basegfx::B3DVector(0,0,1),basegfx::B3DVector(0,0,0),3000,true,0,0.5));
+ Slide.Operations.push_back(new SScale(basegfx::B3DVector(0.01,0.01,0.01),basegfx::B3DVector(0,0,0),true,0,0.5));
+ Slide.Operations.push_back(new STranslate(basegfx::B3DVector(-10000, 0, 0),false, 0.5, 2));
+ maLeavingSlidePrimitives.push_back(Slide);
+
+ Slide.Operations.clear();
+ Slide.Operations.push_back(new SRotate(basegfx::B3DVector(0,0,1),basegfx::B3DVector(0,0,0),-3000,true,0.5,1));
+ Slide.Operations.push_back(new STranslate(basegfx::B3DVector(-100, 0, 0),false, -1, 1));
+ Slide.Operations.push_back(new STranslate(basegfx::B3DVector(100, 0, 0),false, 0.5, 1));
+ Slide.Operations.push_back(new SScale(basegfx::B3DVector(0.01,0.01,0.01),basegfx::B3DVector(0,0,0),false,-1,1));
+ Slide.Operations.push_back(new SScale(basegfx::B3DVector(100,100,100),basegfx::B3DVector(0,0,0),true,0.5,1));
+ maEnteringSlidePrimitives.push_back(Slide);
+
+ OverallOperations.push_back(new SRotate(basegfx::B3DVector(0,0,1),basegfx::B3DVector(0.2,0.2,0),1080,true,0,1));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.hxx b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.hxx
new file mode 100644
index 000000000000..9ebd42c3f820
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionImpl.hxx
@@ -0,0 +1,508 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_OGLTRANS_TRANSITIONIMPL_HXX_
+#define INCLUDED_OGLTRANS_TRANSITIONIMPL_HXX_
+
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b3dvector.hxx>
+
+#include <tools/prewin.h>
+#include <tools/postwin.h>
+
+#if defined( WNT )
+#include <tools/prewin.h>
+#include <tools/postwin.h>
+#elif defined( OS2 )
+#elif defined( QUARTZ )
+#elif defined( UNX )
+#endif
+
+#include <vector>
+#include <GL/gl.h>
+
+using namespace std;
+
+class Primitive;
+class Operation;
+class SceneObject;
+
+
+/** OpenGL 3D Transition class. It implicitly is constructed from XOGLTransition
+
+ This class is capable of making itself into many difference transitions. It holds Primitives and Operations on those primitives.
+*/
+class OGLTransitionImpl
+{
+public:
+ OGLTransitionImpl() :
+ mbUseMipMapLeaving( true ),
+ mbUseMipMapEntering( true ),
+ mnRequiredGLVersion( 1.0 ),
+ maLeavingSlidePrimitives(),
+ maEnteringSlidePrimitives(),
+ maSceneObjects(),
+ mbReflectSlides( false ),
+ mVertexObject( 0 ),
+ mFragmentObject( 0 ),
+ mProgramObject( 0 ),
+ maHelperTexture( 0 ),
+ mmPrepare( NULL ),
+ mmPrepareTransition( NULL ),
+ mmClearTransition( NULL ),
+ mmDisplaySlides( NULL )
+ {}
+
+ ~OGLTransitionImpl();
+
+ void prepare( ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex );
+ void display( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight );
+ void finish();
+
+ void makeOutsideCubeFaceToLeft();
+ void makeInsideCubeFaceToLeft();
+ void makeNByMTileFlip( ::sal_uInt16 n, ::sal_uInt16 m );
+ void makeRevolvingCircles( ::sal_uInt16 nCircles , ::sal_uInt16 nPointsOnCircles );
+ void makeHelix( ::sal_uInt16 nRows );
+ void makeFallLeaving();
+ void makeTurnAround();
+ void makeTurnDown();
+ void makeIris();
+ void makeRochade();
+ void makeVenetianBlinds( bool vertical, int parts );
+ void makeStatic();
+ void makeDissolve();
+ void makeNewsflash();
+
+ /** 2D replacements
+ */
+ void makeDiamond();
+ void makeFadeSmoothly();
+ void makeFadeThroughBlack();
+
+ /** Whether to use mipmaping for slides textures
+ */
+ bool mbUseMipMapLeaving;
+ bool mbUseMipMapEntering;
+
+ /** which GL version does the transition require
+ */
+ float mnRequiredGLVersion;
+
+private:
+ /** clears all the primitives and operations
+ */
+ void clear();
+
+ /** All the primitives that use the leaving slide texture
+ */
+ vector<Primitive> maLeavingSlidePrimitives;
+
+ /** All the primitives that use the leaving slide texture
+ */
+ vector<Primitive> maEnteringSlidePrimitives;
+
+ /** All the surrounding scene objects
+ */
+ vector<SceneObject*> maSceneObjects;
+
+ /** All the operations that should be applied to both leaving and entering slide primitives. These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back.
+ */
+ vector<Operation*> OverallOperations;
+
+ /** Whether to reflect slides, the reflection happens on flat surface beneath the slides.
+ ** Now it only works with slides which keep their rectangular shape together.
+ */
+ bool mbReflectSlides;
+
+ /** GLSL objects, shaders and program
+ */
+ GLuint mVertexObject, mFragmentObject, mProgramObject;
+
+ /** various data */
+ GLuint maHelperTexture;
+
+ /** When this method is not NULL, it is called in display method to prepare the slides, scene, etc.
+ ** We might later replace this by cleaner derived class.
+ */
+ void (OGLTransitionImpl::*mmPrepare)( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight );
+
+ /** When this method is not NULL, it is called after glx context is ready to let the transition prepare GL related things, like GLSL program.
+ ** We might later replace this by cleaner derived class.
+ */
+ void (OGLTransitionImpl::*mmPrepareTransition)( ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex );
+
+ /** When this method is not NULL, it is called when the transition needs to clear after itself, like delete own textures etc.
+ ** We might later replace this by cleaner derived class.
+ */
+ void (OGLTransitionImpl::*mmClearTransition)();
+
+ /** When this method is not NULL, it is called in display method to display the slides.
+ ** We might later replace this by cleaner derived class.
+ */
+ void (OGLTransitionImpl::*mmDisplaySlides)( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale );
+
+ void displaySlides( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale );
+ void displaySlide( double nTime, ::sal_Int32 glSlideTex, std::vector<Primitive>& primitives, double SlideWidthScale, double SlideHeightScale );
+ void displayScene( double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight);
+ void applyOverallOperations( double nTime, double SlideWidthScale, double SlideHeightScale );
+
+ /** various transitions helper methods
+ */
+ void prepareDiamond( double nTime, double SlideWidth, double SlideHeight,double DispWidth, double DispHeight );
+ void displaySlidesFadeSmoothly( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale );
+ void displaySlidesFadeThroughBlack( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale );
+ void displaySlidesRochade( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale );
+ void displaySlidesShaders( double nTime, ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex, double SlideWidthScale, double SlideHeightScale );
+ void prepareStatic( ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex );
+ void prepareDissolve( ::sal_Int32 glLeavingSlideTex, ::sal_Int32 glEnteringSlideTex );
+ void preparePermShader();
+};
+
+class SceneObject
+{
+public:
+ SceneObject();
+
+ virtual void prepare() {};
+ virtual void display(double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight);
+ virtual void finish() {};
+
+ void pushPrimitive (const Primitive &p);
+
+protected:
+ /** All the surrounding scene primitives
+ */
+ vector<Primitive> maPrimitives;
+};
+
+class Iris : public SceneObject
+{
+public:
+ Iris ();
+
+ virtual void prepare();
+ virtual void display(double nTime, double SlideWidth, double SlideHeight, double DispWidth, double DispHeight);
+ virtual void finish();
+
+private:
+
+ GLuint maTexture;
+};
+
+/** This class is a list of Triangles that will share Operations, and could possibly share
+*/
+class Primitive
+{
+public:
+ Primitive() {}
+ // making copy constructor explicit makes the class un-suitable for use with stl containers
+ Primitive(const Primitive& rvalue);
+ ~Primitive();
+
+ void applyOperations(double nTime, double SlideWidthScale, double SlideHeightScale);
+ void display(double nTime, double SlideWidthScale, double SlideHeightScale);
+ const Primitive& operator=(const Primitive& rvalue);
+
+ /** PushBack a vertex,normal, and tex coord. Each SlideLocation is where on the slide is mapped to this location ( from (0,0) to (1,1) ). This will make sure the correct aspect ratio is used, and helps to make slides begin and end at the correct position. (0,0) is the top left of the slide, and (1,1) is the bottom right.
+
+ @param SlideLocation0
+ Location of first Vertex on slide
+
+ @param SlideLocation1
+ Location of second Vertex on slide
+
+ @param SlideLocation2
+ Location of third Vertex on slide
+
+ */
+ void pushTriangle(const basegfx::B2DVector& SlideLocation0,const basegfx::B2DVector& SlideLocation1,const basegfx::B2DVector& SlideLocation2);
+
+ /** clear all the vertices, normals, tex coordinates, and normals
+ */
+ void clearTriangles();
+
+ /** guards against directly changing the vertices
+
+ @return
+ the list of vertices
+ */
+ const vector<basegfx::B3DVector>& getVertices() const {return Vertices;}
+
+ /** guards against directly changing the vertices
+ */
+ const vector<basegfx::B3DVector>& getNormals() const {return Normals;}
+
+ /** guards against directly changing the vertices
+
+ @return
+ the list of Texture Coordinates
+
+ */
+ const vector<basegfx::B2DVector>& getTexCoords() const {return TexCoords;}
+
+ /** list of Operations to be performed on this primitive.These operations will be called in the order they were pushed back in. In OpenGL this effectively uses the operations in the opposite order they were pushed back.
+
+ @return
+ the list of Operations
+
+ */
+ vector<Operation*> Operations;
+
+private:
+ /** list of vertices
+ */
+ vector<basegfx::B3DVector> Vertices;
+
+ /** list of Normals
+ */
+ vector<basegfx::B3DVector> Normals;
+
+ /** list of Texture Coordinates
+ */
+ vector<basegfx::B2DVector> TexCoords;
+};
+
+/** This class is to be derived to make any operation (tranform) you may need in order to construct your transitions
+*/
+class Operation
+{
+public:
+ Operation(){}
+ virtual ~Operation(){}
+
+ /** Should this operation be interpolated . If TRUE, the transform will smoothly move from making no difference from t = 0.0 to nT0 to being completely transformed from t = nT1 to 1. If FALSE, the transform will be inneffectual from t = 0 to nT0, and completely transformed from t = nT0 to 1.
+ */
+ bool bInterpolate;
+
+ /** time to begin the transformation
+ */
+ double nT0;
+
+ /** time to finish the transformation
+ */
+ double nT1;
+public:
+ /** this is the function that is called to give the Operation to OpenGL.
+
+ @param t
+ time from t = 0 to t = 1
+
+ @param SlideWidthScale
+ width of slide divided by width of window
+
+ @param SlideHeightScale
+ height of slide divided by height of window
+
+ */
+ virtual void interpolate(double t,double SlideWidthScale,double SlideHeightScale) = 0;
+
+ /** return a copy of this operation
+ */
+ virtual Operation* clone() = 0;
+};
+
+/** this class is a generic CounterClockWise(CCW) rotation with an axis angle
+*/
+class SRotate: public Operation
+{
+public:
+ void interpolate(double t,double SlideWidthScale,double SlideHeightScale);
+ virtual SRotate* clone();
+
+ /** Constructor
+
+ @param Axis
+ axis to rotate about
+
+ @param Origin
+ position that rotation axis runs through
+
+ @param Angle
+ angle in radians of CCW rotation
+
+ @param bInter
+ see Operation
+
+ @param T0
+ transformation starting time
+
+ @param T1
+ transformation ending time
+
+ */
+ SRotate(const basegfx::B3DVector& Axis,const basegfx::B3DVector& Origin,double Angle,bool bInter, double T0, double T1);
+ ~SRotate(){}
+private:
+ /** axis to rotate CCW about
+ */
+ basegfx::B3DVector axis;
+
+ /** position that rotation axis runs through
+ */
+ basegfx::B3DVector origin;
+
+ /** angle in radians of CCW rotation
+ */
+ double angle;
+};
+
+/** scaling transformation
+*/
+class SScale: public Operation
+{
+public:
+ void interpolate(double t,double SlideWidthScale,double SlideHeightScale);
+ SScale* clone();
+
+ /** Constructor
+
+ @param Scale
+ amount to scale by
+
+ @param Origin
+ position that rotation axis runs through
+
+ @param bInter
+ see Operation
+
+ @param T0
+ transformation starting time
+
+ @param T1
+ transformation ending time
+
+ */
+ SScale(const basegfx::B3DVector& Scale, const basegfx::B3DVector& Origin,bool bInter, double T0, double T1);
+ ~SScale(){}
+private:
+ basegfx::B3DVector scale;
+ basegfx::B3DVector origin;
+};
+
+/** translation transformation
+*/
+class STranslate: public Operation
+{
+public:
+ void interpolate(double t,double SlideWidthScale,double SlideHeightScale);
+ STranslate* clone();
+
+ /** Constructor
+
+ @param Vector
+ vector to translate
+
+ @param bInter
+ see Operation
+
+ @param T0
+ transformation starting time
+
+ @param T1
+ transformation ending time
+
+ */
+ STranslate(const basegfx::B3DVector& Vector,bool bInter, double T0, double T1);
+ ~STranslate(){}
+private:
+ /** vector to translate by
+ */
+ basegfx::B3DVector vector;
+};
+
+/** translation transformation
+*/
+class SEllipseTranslate: public Operation
+{
+public:
+ void interpolate(double t,double SlideWidthScale,double SlideHeightScale);
+ SEllipseTranslate* clone();
+
+ /** Constructor
+
+ @param Vector
+ vector to translate
+
+ @param bInter
+ see Operation
+
+ @param T0
+ transformation starting time
+
+ @param T1
+ transformation ending time
+
+ */
+ SEllipseTranslate(double dWidth, double dHeight, double dStartPosition, double dEndPosition, bool bInter, double T0, double T1);
+ ~SEllipseTranslate(){}
+private:
+ /** width and length of the ellipse
+ */
+ double width, height;
+
+ /** start and end position on the ellipse <0,1>
+ */
+ double startPosition;
+ double endPosition;
+};
+
+/** Same as SRotate, except the depth is scaled by the width of the slide divided by the width of the window.
+*/
+class RotateAndScaleDepthByWidth: public Operation
+{
+public:
+ void interpolate(double t,double SlideWidthScale,double SlideHeightScale);
+ RotateAndScaleDepthByWidth* clone();
+
+ RotateAndScaleDepthByWidth(const basegfx::B3DVector& Axis,const basegfx::B3DVector& Origin,double Angle,bool bInter, double T0, double T1);
+ ~RotateAndScaleDepthByWidth(){}
+private:
+ basegfx::B3DVector axis;
+ basegfx::B3DVector origin;
+ double angle;
+};
+
+/** Same as SRotate, except the depth is scaled by the width of the slide divided by the height of the window.
+*/
+class RotateAndScaleDepthByHeight: public Operation
+{
+public:
+ void interpolate(double t,double SlideWidthScale,double SlideHeightScale);
+ RotateAndScaleDepthByHeight* clone();
+
+ RotateAndScaleDepthByHeight(const basegfx::B3DVector& Axis,const basegfx::B3DVector& Origin,double Angle,bool bInter, double T0, double T1);
+ ~RotateAndScaleDepthByHeight(){}
+private:
+ basegfx::B3DVector axis;
+ basegfx::B3DVector origin;
+ double angle;
+};
+
+#endif // INCLUDED_SLIDESHOW_TRANSITION_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx
new file mode 100644
index 000000000000..33784088d3d5
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx
@@ -0,0 +1,1500 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define GLX_GLXEXT_PROTOTYPES 1
+#include "OGLTrans_TransitionImpl.hxx"
+
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
+#include <com/sun/star/rendering/ColorComponentTag.hpp>
+#include <com/sun/star/rendering/ColorSpaceType.hpp>
+#include <com/sun/star/animations/TransitionType.hpp>
+#include <com/sun/star/animations/TransitionSubType.hpp>
+#include <com/sun/star/presentation/XTransitionFactory.hpp>
+#include <com/sun/star/presentation/XTransition.hpp>
+#include <com/sun/star/presentation/XSlideShowView.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/geometry/IntegerSize2D.hpp>
+
+#include <cppuhelper/compbase1.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/factory.hxx>
+#include <rtl/ref.hxx>
+
+#include <comphelper/servicedecl.hxx>
+
+#include <canvas/canvastools.hxx>
+#include <tools/gen.hxx>
+#include <vcl/window.hxx>
+#include <vcl/syschild.hxx>
+
+#include <boost/noncopyable.hpp>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+
+#if defined( WNT )
+ #include <tools/prewin.h>
+ #include <windows.h>
+ #include <tools/postwin.h>
+ #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+ #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#elif defined( OS2 )
+#elif defined( QUARTZ )
+ #include "premac.h"
+ #include <Cocoa/Cocoa.h>
+ #include "postmac.h"
+#elif defined( UNX )
+namespace unx
+{
+#include <X11/keysym.h>
+#include <X11/X.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+}
+#endif
+#include <vcl/sysdata.hxx>
+
+#ifdef DEBUG
+#include <boost/date_time/posix_time/posix_time.hpp>
+using namespace ::boost::posix_time;
+
+static ptime t1;
+static ptime t2;
+
+#define DBG(x) x
+#else
+#define DBG(x)
+#endif
+
+using namespace ::com::sun::star;
+using ::com::sun::star::beans::XFastPropertySet;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+
+namespace
+{
+
+typedef cppu::WeakComponentImplHelper1<presentation::XTransition> OGLTransitionerImplBase;
+
+namespace
+{
+ struct OGLFormat
+ {
+ GLint nInternalFormat;
+ GLenum eFormat;
+ GLenum eType;
+ };
+
+ /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
+ */
+ int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
+ {
+ using namespace rendering::ColorComponentTag;
+
+ static const sal_Int8 aOrderTable[] =
+ {
+ RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
+ RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
+ ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
+ ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
+ };
+
+ const sal_Int32 nNumComps(rTags.getLength());
+ const sal_Int8* pLine=aOrderTable;
+ for(int i=0; i<4; ++i)
+ {
+ int j=0;
+ while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
+ ++j;
+
+ // all of the line passed, this is a match!
+ if( j==nNumComps )
+ return i;
+
+ pLine+=4;
+ }
+
+ return -1;
+ }
+}
+
+// not thread safe
+static bool errorTriggered;
+int oglErrorHandler( unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/ )
+{
+ errorTriggered = true;
+
+ return 0;
+}
+
+/** This is the Transitioner class for OpenGL 3D transitions in
+ * slideshow. At the moment, it's Linux only. This class is implicitly
+ * constructed from XTransitionFactory.
+*/
+class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable, public OGLTransitionerImplBase
+{
+public:
+ explicit OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition);
+ bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
+ void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
+ static bool initialize( const Reference< presentation::XSlideShowView >& xView );
+
+ // XTransition
+ virtual void SAL_CALL update( double nTime )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
+ const Reference< rendering::XBitmap >& rLeavingBitmap,
+ const Reference< rendering::XBitmap >& rEnteringBitmap )
+ throw (uno::RuntimeException);
+
+protected:
+ void disposeContextAndWindow();
+ void disposeTextures();
+
+ // WeakComponentImplHelperBase
+ virtual void SAL_CALL disposing();
+
+ bool isDisposed() const
+ {
+ return (rBHelper.bDisposed || rBHelper.bInDispose);
+ }
+
+ bool createWindow( Window* pPWindow );
+ void createTexture( unsigned int* texID,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXPixmap pixmap,
+ bool usePixmap,
+#endif
+ bool useMipmap,
+ uno::Sequence<sal_Int8>& data,
+ const OGLFormat* pFormat );
+ void prepareEnvironment ();
+ const OGLFormat* chooseFormats();
+
+private:
+ /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
+ */
+ void GLInitSlides();
+
+
+ /// Holds the information of our new child window
+ struct GLWindow
+ {
+#if defined( WNT )
+ HWND hWnd;
+ HDC hDC;
+ HGLRC hRC;
+#elif defined( OS2 )
+#elif defined( QUARTZ )
+#elif defined( UNX )
+ unx::Display* dpy;
+ int screen;
+ unx::Window win;
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXFBConfig fbc;
+#endif
+ unx::XVisualInfo* vi;
+ unx::GLXContext ctx;
+#endif
+ unsigned int bpp;
+ unsigned int Width;
+ unsigned int Height;
+ const char* GLXExtensions;
+ const GLubyte* GLExtensions;
+
+ bool HasGLXExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, (const GLubyte*) GLXExtensions ); }
+ bool HasGLExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, GLExtensions ); }
+ } GLWin;
+
+ /** OpenGL handle to the leaving slide's texture
+ */
+ unsigned int GLleavingSlide;
+ /** OpenGL handle to the entering slide's texture
+ */
+ unsigned int GLenteringSlide;
+
+ /** pointer to our window which we MIGHT create.
+ */
+ class SystemChildWindow* pWindow;
+
+ Reference< presentation::XSlideShowView > mxView;
+ Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
+ Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
+
+ /** raw bytes of the entering bitmap
+ */
+ uno::Sequence<sal_Int8> EnteringBytes;
+
+ /** raw bytes of the leaving bitmap
+ */
+ uno::Sequence<sal_Int8> LeavingBytes;
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXPixmap LeavingPixmap;
+ unx::GLXPixmap EnteringPixmap;
+#endif
+ bool mbRestoreSync;
+ bool mbUseLeavingPixmap;
+ bool mbUseEnteringPixmap;
+ bool mbFreeLeavingPixmap;
+ bool mbFreeEnteringPixmap;
+ unx::Pixmap maLeavingPixmap;
+ unx::Pixmap maEnteringPixmap;
+
+ /** the form the raw bytes are in for the bitmaps
+ */
+ rendering::IntegerBitmapLayout SlideBitmapLayout;
+
+ /** the size of the slides
+ */
+ geometry::IntegerSize2D SlideSize;
+
+ /** Our Transition to be used.
+ */
+ OGLTransitionImpl* pTransition;
+
+public:
+ /** whether we are running on ATI fglrx with bug related to textures
+ */
+ static bool cbBrokenTexturesATI;
+
+ /** GL version
+ */
+ static float cnGLVersion;
+ float mnGLXVersion;
+
+ /** Whether Mesa is the OpenGL vendor
+ */
+ static bool cbMesa;
+
+ /**
+ whether the display has GLX extension
+ */
+ static bool cbGLXPresent;
+
+ /**
+ whether texture from pixmap extension is available
+ */
+ bool mbTextureFromPixmap;
+
+ /**
+ whether to generate mipmaped textures
+ */
+ bool mbGenerateMipmap;
+
+ /**
+ whether we have visual which can be used for texture_from_pixmap extension
+ */
+ bool mbHasTFPVisual;
+
+#ifdef DEBUG
+ ptime t3;
+ ptime t4;
+ ptime t5;
+ ptime t6;
+ time_duration total_update;
+ int frame_count;
+#endif
+};
+
+// declare the static variables as some gcc versions have problems declaring them automaticaly
+bool OGLTransitionerImpl::cbBrokenTexturesATI;
+float OGLTransitionerImpl::cnGLVersion;
+bool OGLTransitionerImpl::cbMesa;
+bool OGLTransitionerImpl::cbGLXPresent;
+
+bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView )
+{
+ // not thread safe
+ static bool initialized = false;
+
+ if( !initialized ) {
+ OGLTransitionerImpl *instance;
+
+ instance = new OGLTransitionerImpl( NULL );
+ if( instance->initWindowFromSlideShowView( xView ) ) {
+
+ const GLubyte* version = glGetString( GL_VERSION );
+ if( version && version[0] ) {
+ cnGLVersion = version[0] - '0';
+ if( version[1] == '.' && version[2] )
+ cnGLVersion += (version[2] - '0')/10.0;
+ } else
+ cnGLVersion = 1.0;
+ OSL_TRACE("GL version: %s parsed: %f", version, cnGLVersion );
+
+ const GLubyte* vendor = glGetString( GL_VENDOR );
+ cbMesa = ( vendor && strstr( (const char *) vendor, "Mesa" ) );
+ OSL_TRACE("GL vendor: %s identified as Mesa: %d", vendor, cbMesa );
+
+ /* TODO: check for version once the bug in fglrx driver is fixed */
+ cbBrokenTexturesATI = (vendor && strcmp( (const char *) vendor, "ATI Technologies Inc." ) == 0 );
+
+ instance->disposing();
+ cbGLXPresent = true;
+ } else
+ cbGLXPresent = false;
+
+ delete instance;
+ initialized = true;
+ }
+
+ return cbGLXPresent;
+}
+
+bool OGLTransitionerImpl::createWindow( Window* pPWindow )
+{
+ const SystemEnvData* sysData(pPWindow->GetSystemData());
+#if defined( WNT )
+ GLWin.hWnd = sysData->hWnd;
+#elif defined( UNX )
+ GLWin.dpy = reinterpret_cast<unx::Display*>(sysData->pDisplay);
+
+ if( unx::glXQueryExtension( GLWin.dpy, NULL, NULL ) == false )
+ return false;
+
+ GLWin.win = sysData->aWindow;
+
+ OSL_TRACE("parent window: %d", GLWin.win);
+
+ unx::XWindowAttributes xattr;
+ unx::XGetWindowAttributes( GLWin.dpy, GLWin.win, &xattr );
+
+ GLWin.screen = XScreenNumberOfScreen( xattr.screen );
+
+ unx::XVisualInfo* vi( NULL );
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::XVisualInfo* visinfo;
+ unx::XVisualInfo* firstVisual( NULL );
+#endif
+ static int attrList3[] =
+ {
+ GLX_RGBA,//only TrueColor or DirectColor
+ //single buffered
+ GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
+ GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
+ GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
+ GLX_DEPTH_SIZE,0,//no depth buffer
+ None
+ };
+ static int attrList2[] =
+ {
+ GLX_RGBA,//only TrueColor or DirectColor
+ /// single buffered
+ GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
+ GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
+ GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
+ GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
+ None
+ };
+ static int attrList1[] =
+ {
+ GLX_RGBA,//only TrueColor or DirectColor
+ GLX_DOUBLEBUFFER,/// only double buffer
+ GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
+ GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
+ GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
+ GLX_DEPTH_SIZE,0,/// no depth buffer
+ None
+ };
+ static int attrList0[] =
+ {
+ GLX_RGBA,//only TrueColor or DirectColor
+ GLX_DOUBLEBUFFER,/// only double buffer
+ GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
+ GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
+ GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
+ GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
+ None
+ };
+ static int* attrTable[] =
+ {
+ attrList0,
+ attrList1,
+ attrList2,
+ attrList3,
+ NULL
+ };
+ int** pAttributeTable = attrTable;
+ const SystemEnvData* pChildSysData = NULL;
+ delete pWindow;
+ pWindow=NULL;
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXFBConfig* fbconfigs = NULL;
+ int nfbconfigs, value, i = 0;
+#endif
+
+ while( *pAttributeTable )
+ {
+ // try to find a visual for the current set of attributes
+ vi = unx::glXChooseVisual( GLWin.dpy,
+ GLWin.screen,
+ *pAttributeTable );
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ if( vi ) {
+ if( !firstVisual )
+ firstVisual = vi;
+ OSL_TRACE("trying VisualID %08X", vi->visualid);
+ fbconfigs = glXGetFBConfigs (GLWin.dpy, GLWin.screen, &nfbconfigs);
+ for ( ; i < nfbconfigs; i++)
+ {
+ visinfo = glXGetVisualFromFBConfig (GLWin.dpy, fbconfigs[i]);
+ if( !visinfo || visinfo->visualid != vi->visualid )
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
+ if (!(value & GLX_PIXMAP_BIT))
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+ &value);
+ if (!(value & GLX_TEXTURE_2D_BIT_EXT))
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGB_EXT,
+ &value);
+ if (value == FALSE)
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
+ GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+ &value);
+ if (value == FALSE)
+ continue;
+
+ /* TODO: handle non Y inverted cases */
+ break;
+ }
+
+ if( i != nfbconfigs || ( firstVisual && pAttributeTable[1] == NULL ) ) {
+ if( i != nfbconfigs ) {
+ vi = glXGetVisualFromFBConfig( GLWin.dpy, fbconfigs[i] );
+ mbHasTFPVisual = true;
+ OSL_TRACE("found visual suitable for texture_from_pixmap");
+ } else {
+ vi = firstVisual;
+ mbHasTFPVisual = false;
+ OSL_TRACE("did not find visual suitable for texture_from_pixmap, using %08X", vi->visualid);
+ }
+#else
+ if( vi ) {
+#endif
+ SystemWindowData winData;
+ winData.nSize = sizeof(winData);
+ OSL_TRACE("using VisualID %08X", vi->visualid);
+ winData.pVisual = (void*)(vi->visual);
+ pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
+ pChildSysData = pWindow->GetSystemData();
+ if( pChildSysData ) {
+ break;
+ } else {
+ delete pWindow, pWindow=NULL;
+ }
+ }
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ }
+#endif
+
+ ++pAttributeTable;
+ }
+#endif
+
+#if defined( WNT )
+ const SystemEnvData* pChildSysData = NULL;
+ SystemWindowData winData;
+ winData.nSize = sizeof(winData);
+ pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
+ pChildSysData = pWindow->GetSystemData();
+#endif
+
+ if( pWindow )
+ {
+ pWindow->SetMouseTransparent( TRUE );
+ pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ pWindow->EnableEraseBackground( FALSE );
+ pWindow->SetControlForeground();
+ pWindow->SetControlBackground();
+ pWindow->EnablePaint(FALSE);
+#if defined( WNT )
+ GLWin.hWnd = sysData->hWnd;
+#elif defined( UNX )
+ GLWin.dpy = reinterpret_cast<unx::Display*>(pChildSysData->pDisplay);
+ GLWin.win = pChildSysData->aWindow;
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ if( mbHasTFPVisual )
+ GLWin.fbc = fbconfigs[i];
+#endif
+ GLWin.vi = vi;
+ GLWin.GLXExtensions = unx::glXQueryExtensionsString( GLWin.dpy, GLWin.screen );
+ OSL_TRACE("available GLX extensions: %s", GLWin.GLXExtensions);
+#endif
+
+ return true;
+ }
+
+ return false;
+}
+
+bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ mxView.set( xView, UNO_QUERY );
+ if( !mxView.is() )
+ return false;
+
+ /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
+ uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
+ uno::Sequence< uno::Any > aDeviceParams;
+ ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
+
+ ::rtl::OUString aImplName;
+ aDeviceParams[ 0 ] >>= aImplName;
+
+ sal_Int64 aVal = 0;
+ aDeviceParams[1] >>= aVal;
+ if( !createWindow( reinterpret_cast< Window* >( aVal ) ) )
+ return false;
+
+ awt::Rectangle aCanvasArea = mxView->getCanvasArea();
+ pWindow->SetPosSizePixel(aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
+ GLWin.Width = aCanvasArea.Width;
+ GLWin.Height = aCanvasArea.Height;
+ OSL_TRACE("canvas area: %d,%d - %dx%d", aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
+
+#if defined( WNT )
+ GLWin.hDC = GetDC(GLWin.hWnd);
+#elif defined( UNX )
+ GLWin.ctx = glXCreateContext(GLWin.dpy,
+ GLWin.vi,
+ 0,
+ GL_TRUE);
+ if( GLWin.ctx == NULL ) {
+ OSL_TRACE("unable to create GLX context");
+ return false;
+ }
+#endif
+
+#if defined( WNT )
+ PIXELFORMATDESCRIPTOR PixelFormatFront = // PixelFormat Tells Windows How We Want Things To Be
+ {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1, // Version Number
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER,
+ PFD_TYPE_RGBA, // Request An RGBA Format
+ (BYTE)32, // Select Our Color Depth
+ 0, 0, 0, 0, 0, 0, // Color Bits Ignored
+ 0, // No Alpha Buffer
+ 0, // Shift Bit Ignored
+ 0, // No Accumulation Buffer
+ 0, 0, 0, 0, // Accumulation Bits Ignored
+ 64, // 32 bit Z-BUFFER
+ 0, // 0 bit stencil buffer
+ 0, // No Auxiliary Buffer
+ 0, // now ignored
+ 0, // Reserved
+ 0, 0, 0 // Layer Masks Ignored
+ };
+ int WindowPix = ChoosePixelFormat(GLWin.hDC,&PixelFormatFront);
+ SetPixelFormat(GLWin.hDC,WindowPix,&PixelFormatFront);
+ GLWin.hRC = wglCreateContext(GLWin.hDC);
+ wglMakeCurrent(GLWin.hDC,GLWin.hRC);
+#elif defined( UNX )
+ if( !glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx ) ) {
+ OSL_TRACE("unable to select current GLX context");
+ return false;
+ }
+
+ int glxMinor, glxMajor;
+ mnGLXVersion = 0;
+ if( glXQueryVersion( GLWin.dpy, &glxMajor, &glxMinor ) )
+ mnGLXVersion = glxMajor + 0.1*glxMinor;
+ OSL_TRACE("available GLX version: %f", mnGLXVersion);
+
+ GLWin.GLExtensions = glGetString( GL_EXTENSIONS );
+ OSL_TRACE("available GL extensions: %s", GLWin.GLExtensions);
+
+ mbTextureFromPixmap = GLWin.HasGLXExtension( "GLX_EXT_texture_from_pixmap" );
+ mbGenerateMipmap = GLWin.HasGLExtension( "GL_SGIS_generate_mipmap" );
+
+ if( GLWin.HasGLXExtension("GLX_SGI_swap_control" ) ) {
+ // enable vsync
+ typedef GLint (*glXSwapIntervalProc)(GLint);
+ glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) unx::glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
+ if( glXSwapInterval ) {
+ int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
+
+ // replace error handler temporarily
+ oldHandler = unx::XSetErrorHandler( oglErrorHandler );
+
+ errorTriggered = false;
+
+ glXSwapInterval( 1 );
+
+ // sync so that we possibly get an XError
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ if( errorTriggered )
+ OSL_TRACE("error when trying to set swap interval, NVIDIA or Mesa bug?");
+ else
+ OSL_TRACE("set swap interval to 1 (enable vsync)");
+
+ // restore the error handler
+ unx::XSetErrorHandler( oldHandler );
+ }
+ }
+#endif
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glClearColor (0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+#if defined( WNT )
+ SwapBuffers(GLWin.hDC);
+#elif defined( UNX )
+ unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
+#endif
+
+ glEnable(GL_LIGHTING);
+ GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
+ GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
+ glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
+ glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_NORMALIZE);
+
+ if( LeavingBytes.hasElements() && EnteringBytes.hasElements())
+ GLInitSlides();//we already have uninitialized slides, let's initialize
+
+ if( pTransition && pTransition->mnRequiredGLVersion <= cnGLVersion )
+ pTransition->prepare( GLleavingSlide, GLenteringSlide );
+
+ return true;
+}
+
+void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
+ const uno::Reference< rendering::XBitmap >& xEnteringSlide )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return;
+
+ mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
+ mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
+ Reference< XFastPropertySet > xLeavingSet( xLeavingSlide , UNO_QUERY );
+ Reference< XFastPropertySet > xEnteringSet( xEnteringSlide , UNO_QUERY );
+
+ geometry::IntegerRectangle2D SlideRect;
+ SlideSize = mxLeavingBitmap->getSize();
+ SlideRect.X1 = 0;
+ SlideRect.X2 = SlideSize.Width;
+ SlideRect.Y1 = 0;
+ SlideRect.Y2 = SlideSize.Height;
+
+ OSL_TRACE("leaving bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
+ SlideSize = mxEnteringBitmap->getSize();
+ OSL_TRACE("entering bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
+
+#ifdef UNX
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+#endif
+
+#ifdef DEBUG
+ t1 = microsec_clock::local_time();
+#endif
+
+ mbUseLeavingPixmap = false;
+ mbUseEnteringPixmap = false;
+
+#ifdef UNX
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+
+ if( mnGLXVersion >= 1.2999 && mbTextureFromPixmap && xLeavingSet.is() && xEnteringSet.is() && mbHasTFPVisual ) {
+ Sequence< Any > leaveArgs;
+ Sequence< Any > enterArgs;
+ if( (xLeavingSet->getFastPropertyValue( 1 ) >>= leaveArgs) &&
+ (xEnteringSet->getFastPropertyValue( 1 ) >>= enterArgs) ) {
+ OSL_TRACE ("pixmaps available");
+
+ sal_Int32 depth;
+
+ leaveArgs[0] >>= mbFreeLeavingPixmap;
+ enterArgs[0] >>= mbFreeEnteringPixmap;
+ leaveArgs[1] >>= maLeavingPixmap;
+ enterArgs[1] >>= maEnteringPixmap;
+ leaveArgs[2] >>= depth;
+
+ int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+ GLX_MIPMAP_TEXTURE_EXT, True,
+ None };
+
+
+ // sync so that we possibly get an pending XError, before we set our handler.
+ // this way we will not miss any error from other code
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
+
+ // replace error handler temporarily
+ oldHandler = unx::XSetErrorHandler( oglErrorHandler );
+
+ errorTriggered = false;
+ LeavingPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maLeavingPixmap, pixmapAttribs );
+
+ // sync so that we possibly get an XError
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ if( !errorTriggered )
+ mbUseLeavingPixmap = true;
+ else {
+ OSL_TRACE("XError triggered");
+ if( mbFreeLeavingPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
+ mbFreeLeavingPixmap = false;
+ }
+ errorTriggered = false;
+ }
+
+ EnteringPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maEnteringPixmap, pixmapAttribs );
+
+ // sync so that we possibly get an XError
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ OSL_TRACE("created glx pixmap %p and %p depth: %d", LeavingPixmap, EnteringPixmap, depth);
+ if( !errorTriggered )
+ mbUseEnteringPixmap = true;
+ else {
+ OSL_TRACE("XError triggered");
+ if( mbFreeEnteringPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
+ mbFreeEnteringPixmap = false;
+ }
+ }
+
+ // restore the error handler
+ unx::XSetErrorHandler( oldHandler );
+ }
+ }
+
+#endif
+#endif
+ if( !mbUseLeavingPixmap )
+ LeavingBytes = mxLeavingBitmap->getData(SlideBitmapLayout,SlideRect);
+ if( !mbUseEnteringPixmap )
+ EnteringBytes = mxEnteringBitmap->getData(SlideBitmapLayout,SlideRect);
+
+// TODO
+#ifdef UNX
+ if(GLWin.ctx)//if we have a rendering context, let's init the slides
+#endif
+ GLInitSlides();
+
+ OSL_ENSURE(SlideBitmapLayout.PlaneStride == 0,"only handle no plane stride now");
+
+#ifdef UNX
+ /* flush & sync */
+ unx::glXWaitGL();
+ XSync( GLWin.dpy, false );
+
+ // synchronized X still gives us much smoother play
+ // I suspect some issues in above code in slideshow
+ // synchronize whole transition for now
+ XSynchronize( GLWin.dpy, true );
+ mbRestoreSync = true;
+#endif
+}
+
+void OGLTransitionerImpl::createTexture( unsigned int* texID,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXPixmap pixmap,
+ bool usePixmap,
+#endif
+ bool useMipmap,
+ uno::Sequence<sal_Int8>& data,
+ const OGLFormat* pFormat )
+{
+ glDeleteTextures( 1, texID );
+ glGenTextures( 1, texID );
+ glBindTexture( GL_TEXTURE_2D, *texID );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::PFNGLXBINDTEXIMAGEEXTPROC myglXBindTexImageEXT = (unx::PFNGLXBINDTEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXBindTexImageEXT" );
+
+ if( usePixmap ) {
+ if( mbGenerateMipmap )
+ glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, True);
+ myglXBindTexImageEXT (GLWin.dpy, pixmap, GLX_FRONT_LEFT_EXT, NULL);
+ if( mbGenerateMipmap && useMipmap ) {
+ OSL_TRACE("use mipmaps");
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
+ } else {
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ }
+ } else {
+#endif
+ if( !pFormat )
+ {
+ // force-convert color to ARGB8888 int color space
+ uno::Sequence<sal_Int8> tempBytes(
+ SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
+ data,
+ canvas::tools::getStdColorSpace()));
+ gluBuild2DMipmaps(GL_TEXTURE_2D,
+ 4,
+ SlideSize.Width,
+ SlideSize.Height,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ &tempBytes[0]);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
+
+ //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
+ GLfloat largest_supported_anisotropy;
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
+ } else {
+ if( pTransition && !cbBrokenTexturesATI && !useMipmap) {
+ glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ } else {
+ gluBuild2DMipmaps( GL_TEXTURE_2D, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); //TRILINEAR FILTERING
+
+ //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
+ GLfloat largest_supported_anisotropy;
+ glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
+ }
+ }
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ }
+#endif
+ OSL_ENSURE(glIsTexture(*texID), "Can't generate Leaving slide textures in OpenGL");
+}
+
+void OGLTransitionerImpl::prepareEnvironment()
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ double EyePos(10.0);
+ double RealF(1.0);
+ double RealN(-1.0);
+ double RealL(-1.0);
+ double RealR(1.0);
+ double RealB(-1.0);
+ double RealT(1.0);
+ double ClipN(EyePos+5.0*RealN);
+ double ClipF(EyePos+15.0*RealF);
+ double ClipL(RealL*8.0);
+ double ClipR(RealR*8.0);
+ double ClipB(RealB*8.0);
+ double ClipT(RealT*8.0);
+ //This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
+ glScaled( 1.0 / ( ( ( RealR * 2.0 * ClipN ) / ( EyePos * ( ClipR - ClipL ) ) ) - ( ( ClipR + ClipL ) / ( ClipR - ClipL ) ) ),
+ 1.0 / ( ( ( RealT * 2.0 * ClipN ) / ( EyePos * ( ClipT - ClipB ) ) ) - ( ( ClipT + ClipB ) / ( ClipT - ClipB ) ) ),
+ 1.0 );
+ glFrustum(ClipL,ClipR,ClipB,ClipT,ClipN,ClipF);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslated(0,0,-EyePos);
+}
+
+const OGLFormat* OGLTransitionerImpl::chooseFormats()
+{
+ const OGLFormat* pDetectedFormat=NULL;
+ uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
+ SlideBitmapLayout.ColorSpace);
+
+ if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
+ xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) )
+ {
+ /* table for canvas->OGL format mapping. outer index is number
+ of color components (0:3, 1:4), then comes bits per pixel
+ (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
+ 2:argb, 3:abgr)
+ */
+ static const OGLFormat lcl_RGB24[] =
+ {
+ // 24 bit RGB
+ {3, GL_BGR, GL_UNSIGNED_BYTE},
+ {3, GL_RGB, GL_UNSIGNED_BYTE},
+ {3, GL_BGR, GL_UNSIGNED_BYTE},
+ {3, GL_RGB, GL_UNSIGNED_BYTE}
+ };
+
+#if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
+ // more format constants available
+ static const OGLFormat lcl_RGB16[] =
+ {
+ // 16 bit RGB
+ {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
+ {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
+ {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
+ {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
+ };
+
+ static const OGLFormat lcl_ARGB16_4[] =
+ {
+ // 16 bit ARGB
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
+ };
+
+ static const OGLFormat lcl_ARGB16_5[] =
+ {
+ // 16 bit ARGB
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
+ };
+
+ static const OGLFormat lcl_ARGB32[] =
+ {
+ // 32 bit ARGB
+ {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
+ {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
+ {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
+ {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
+ };
+
+ const uno::Sequence<sal_Int8> aComponentTags(
+ xIntColorSpace->getComponentTags());
+ const uno::Sequence<sal_Int32> aComponentBitcounts(
+ xIntColorSpace->getComponentBitCounts());
+ const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
+ const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
+
+ // supported component ordering?
+ const int nComponentOrderIndex(
+ calcComponentOrderIndex(aComponentTags));
+ if( nComponentOrderIndex != -1 )
+ {
+ switch( nBitsPerPixel )
+ {
+ case 16:
+ if( nNumComponents == 3 )
+ {
+ pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
+ }
+ else if( nNumComponents == 4 )
+ {
+ if( aComponentBitcounts[1] == 4 )
+ {
+ pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
+ }
+ else if( aComponentBitcounts[1] == 5 )
+ {
+ pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
+ }
+ }
+ break;
+ case 24:
+ if( nNumComponents == 3 )
+ {
+ pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
+ }
+ break;
+ case 32:
+ pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
+ break;
+ }
+ }
+#else
+ const uno::Sequence<sal_Int8> aComponentTags(
+ xIntColorSpace->getComponentTags());
+ const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
+ if( aComponentTags.getLength() == 3 &&
+ nComponentOrderIndex != -1 &&
+ xIntColorSpace->getBitsPerPixel() == 24 )
+ {
+ pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
+ }
+#endif
+ }
+
+ return pDetectedFormat;
+}
+
+void OGLTransitionerImpl::GLInitSlides()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed() || pTransition->mnRequiredGLVersion > cnGLVersion)
+ return;
+
+ prepareEnvironment();
+
+ const OGLFormat* pFormat = NULL;
+ if( !mbUseLeavingPixmap || !mbUseEnteringPixmap )
+ pFormat = chooseFormats();
+
+ createTexture( &GLleavingSlide,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ LeavingPixmap,
+ mbUseLeavingPixmap,
+#endif
+ pTransition->mbUseMipMapLeaving,
+ LeavingBytes,
+ pFormat );
+
+ createTexture( &GLenteringSlide,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ EnteringPixmap,
+ mbUseEnteringPixmap,
+#endif
+ pTransition->mbUseMipMapEntering,
+ EnteringBytes,
+ pFormat );
+
+#ifdef UNX
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+#endif
+
+#ifdef DEBUG
+ t2 = microsec_clock::local_time();
+ OSL_TRACE("textures created in: %s", to_simple_string( t2 - t1 ).c_str());
+#endif
+}
+
+void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException)
+{
+#ifdef DEBUG
+ frame_count ++;
+ t3 = microsec_clock::local_time();
+ if( frame_count == 1 ) {
+ t5 = t3;
+ total_update = seconds (0);
+ }
+#endif
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed() || !cbGLXPresent || pTransition->mnRequiredGLVersion > cnGLVersion)
+ return;
+
+#ifdef WNT
+ wglMakeCurrent(GLWin.hDC,GLWin.hRC);
+#endif
+#ifdef UNX
+ glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+#endif
+
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if(pTransition)
+ pTransition->display( nTime, GLleavingSlide, GLenteringSlide,
+ SlideSize.Width, SlideSize.Height,
+ static_cast<double>(GLWin.Width),
+ static_cast<double>(GLWin.Height) );
+
+#if defined( WNT )
+ SwapBuffers(GLWin.hDC);
+#elif defined( UNX )
+ unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
+#endif
+ if( pWindow )
+ pWindow->Show();
+
+#ifdef UNX
+ /* flush & sync */
+ unx::glXWaitGL();
+ XSync( GLWin.dpy, false );
+#endif
+
+#ifdef DEBUG
+ t4 = microsec_clock::local_time();
+
+ OSL_TRACE("update time: %f", nTime);
+ OSL_TRACE("update took: %s", to_simple_string( t4 - t3 ).c_str());
+ total_update += (t4 - t3);
+#endif
+}
+
+void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
+ const Reference< rendering::XBitmap >& rLeavingBitmap,
+ const Reference< rendering::XBitmap >& rEnteringBitmap )
+ throw (uno::RuntimeException)
+{
+ OSL_TRACE("transitioner: view changed");
+
+ disposeTextures();
+ disposeContextAndWindow();
+
+ initWindowFromSlideShowView( rView );
+ setSlides( rLeavingBitmap, rEnteringBitmap );
+}
+
+void OGLTransitionerImpl::disposeContextAndWindow()
+{
+#if defined( WNT )
+ if (GLWin.hRC)
+ {
+ wglMakeCurrent( GLWin.hDC, 0 ); // kill Device Context
+ wglDeleteContext( GLWin.hRC ); // Kill Render Context
+ ReleaseDC( GLWin.hWnd, GLWin.hDC ); // Release Window
+ }
+#elif defined( UNX )
+ if(GLWin.ctx)
+ {
+ glXMakeCurrent(GLWin.dpy, None, NULL);
+ if( glGetError() != GL_NO_ERROR ) {
+ OSL_TRACE("glError: %s", (char *)gluErrorString(glGetError()));
+ }
+ glXDestroyContext(GLWin.dpy, GLWin.ctx);
+ GLWin.ctx = NULL;
+ }
+#endif
+ if( pWindow ) {
+ delete pWindow;
+ pWindow = NULL;
+ GLWin.win = 0;
+ }
+}
+
+void OGLTransitionerImpl::disposeTextures()
+{
+ if( !GLWin.ctx )
+ return;
+
+#ifdef WNT
+ wglMakeCurrent(GLWin.hDC,GLWin.hRC);
+#endif
+#ifdef UNX
+ glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+#endif
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::PFNGLXRELEASETEXIMAGEEXTPROC myglXReleaseTexImageEXT = (unx::PFNGLXRELEASETEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXReleaseTexImageEXT" );
+ if( mbUseLeavingPixmap ) {
+
+ myglXReleaseTexImageEXT( GLWin.dpy, LeavingPixmap, GLX_FRONT_LEFT_EXT );
+ glXDestroyGLXPixmap( GLWin.dpy, LeavingPixmap );
+ LeavingPixmap = 0;
+ if( mbFreeLeavingPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
+ mbFreeLeavingPixmap = false;
+ maLeavingPixmap = 0;
+ }
+ }
+ if( mbUseEnteringPixmap ) {
+ myglXReleaseTexImageEXT( GLWin.dpy, EnteringPixmap, GLX_FRONT_LEFT_EXT );
+ glXDestroyGLXPixmap( GLWin.dpy, EnteringPixmap );
+ EnteringPixmap = 0;
+ if( mbFreeEnteringPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
+ mbFreeEnteringPixmap = false;
+ maEnteringPixmap = 0;
+ }
+ }
+#endif
+
+ if( !mbUseLeavingPixmap ) {
+ glDeleteTextures(1,&GLleavingSlide);
+ GLleavingSlide = 0;
+ }
+ if( !mbUseEnteringPixmap ) {
+ glDeleteTextures(1,&GLenteringSlide);
+ GLleavingSlide = 0;
+ }
+
+ mbUseLeavingPixmap = false;
+ mbUseEnteringPixmap = false;
+}
+
+// we are about to be disposed (someone call dispose() on us)
+void OGLTransitionerImpl::disposing()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+#ifdef DEBUG
+ OSL_TRACE("dispose %p\n", this);
+ if( frame_count ) {
+ t6 = microsec_clock::local_time();
+ time_duration duration = t6 - t5;
+ OSL_TRACE("whole transition (frames: %d) took: %s fps: %f time spent in updates: %s percentage of transition time: %f%%",
+ frame_count, to_simple_string( duration ).c_str(),
+ ((double)frame_count*1000000000.0)/duration.total_nanoseconds(),
+ to_simple_string( total_update ).c_str(),
+ 100*(((double)total_update.total_nanoseconds())/((double)duration.total_nanoseconds()))
+ );
+ }
+#endif
+
+ if( pWindow ) {
+
+ disposeTextures();
+
+ if (pTransition)
+ pTransition->finish();
+
+#ifdef UNX
+ if( mbRestoreSync ) {
+ // try to reestablish synchronize state
+ char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
+ XSynchronize( GLWin.dpy, sal_synchronize && *sal_synchronize == '1' );
+ }
+#endif
+
+ disposeContextAndWindow();
+ }
+
+ if (pTransition)
+ delete pTransition;
+
+ mxLeavingBitmap.clear();
+ mxEnteringBitmap.clear();
+ mxView.clear();
+}
+
+OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) :
+ OGLTransitionerImplBase(m_aMutex),
+ GLWin(),
+ GLleavingSlide( 0 ),
+ GLenteringSlide( 0 ),
+ pWindow( NULL ),
+ mxView(),
+ mxLeavingBitmap(),
+ mxEnteringBitmap(),
+ EnteringBytes(),
+ LeavingBytes(),
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ LeavingPixmap(0),
+ EnteringPixmap(0),
+#endif
+ mbRestoreSync( false ),
+ mbUseLeavingPixmap( false ),
+ mbUseEnteringPixmap( false ),
+ mbFreeLeavingPixmap( false ),
+ mbFreeEnteringPixmap( false ),
+ maLeavingPixmap(0),
+ maEnteringPixmap(0),
+ SlideBitmapLayout(),
+ SlideSize(),
+ pTransition(pOGLTransition)
+{
+#if defined( WNT )
+ GLWin.hWnd = 0;
+#elif defined( UNX )
+ GLWin.ctx = 0;
+#endif
+
+ DBG(frame_count = 0);
+}
+
+typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
+
+class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
+{
+public:
+ explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) :
+ OGLTransitionFactoryImplBase(m_aMutex)
+ {}
+
+ // XTransitionFactory
+ virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException)
+ {
+ if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
+ switch( transitionSubType )
+ {
+ case animations::TransitionSubType::ACROSS:
+ case animations::TransitionSubType::CORNERSOUT:
+ case animations::TransitionSubType::CIRCLE:
+ case animations::TransitionSubType::FANOUTHORIZONTAL:
+ case animations::TransitionSubType::CORNERSIN:
+ case animations::TransitionSubType::LEFTTORIGHT:
+ case animations::TransitionSubType::TOPTOBOTTOM:
+ case animations::TransitionSubType::TOPRIGHT:
+ case animations::TransitionSubType::TOPLEFT:
+ case animations::TransitionSubType::BOTTOMRIGHT:
+ case animations::TransitionSubType::BOTTOMLEFT:
+ case animations::TransitionSubType::TOPCENTER:
+ case animations::TransitionSubType::RIGHTCENTER:
+ case animations::TransitionSubType::BOTTOMCENTER:
+ return sal_True;
+
+ default:
+ return sal_False;
+ }
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
+ return sal_True;
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
+ return sal_True;
+ } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
+ return sal_True;
+ } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
+ return sal_True;
+ } else
+ return sal_False;
+ }
+
+ virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
+ ::sal_Int16 transitionType,
+ ::sal_Int16 transitionSubType,
+ const uno::Reference< presentation::XSlideShowView >& view,
+ const uno::Reference< rendering::XBitmap >& leavingBitmap,
+ const uno::Reference< rendering::XBitmap >& enteringBitmap )
+ throw (uno::RuntimeException)
+ {
+ if( !hasTransition( transitionType, transitionSubType ) )
+ return uno::Reference< presentation::XTransition >();
+
+ bool bGLXPresent = OGLTransitionerImpl::initialize( view );
+
+ if( OGLTransitionerImpl::cbMesa && (
+ ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) ||
+ ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) ||
+ ( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) ) )
+ return uno::Reference< presentation::XTransition >();
+
+
+ OGLTransitionImpl* pTransition = NULL;
+
+ if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
+ pTransition = new OGLTransitionImpl();
+ switch( transitionSubType )
+ {
+ case animations::TransitionSubType::ACROSS:
+ pTransition->makeNByMTileFlip(8,6);
+ break;
+ case animations::TransitionSubType::CORNERSOUT:
+ pTransition->makeOutsideCubeFaceToLeft();
+ break;
+ case animations::TransitionSubType::CIRCLE:
+ pTransition->makeRevolvingCircles(8,128);
+ break;
+ case animations::TransitionSubType::FANOUTHORIZONTAL:
+ pTransition->makeHelix(20);
+ break;
+ case animations::TransitionSubType::CORNERSIN:
+ pTransition->makeInsideCubeFaceToLeft();
+ break;
+ case animations::TransitionSubType::LEFTTORIGHT:
+ pTransition->makeFallLeaving();
+ break;
+ case animations::TransitionSubType::TOPTOBOTTOM:
+ pTransition->makeTurnAround();
+ break;
+ case animations::TransitionSubType::TOPRIGHT:
+ pTransition->makeTurnDown();
+ break;
+ case animations::TransitionSubType::TOPLEFT:
+ pTransition->makeIris();
+ break;
+ case animations::TransitionSubType::BOTTOMRIGHT:
+ pTransition->makeRochade();
+ break;
+ case animations::TransitionSubType::BOTTOMLEFT:
+ pTransition->makeVenetianBlinds( true, 8 );
+ break;
+ case animations::TransitionSubType::TOPCENTER:
+ pTransition->makeVenetianBlinds( false, 6 );
+ break;
+ case animations::TransitionSubType::RIGHTCENTER:
+ pTransition->makeStatic();
+ break;
+ case animations::TransitionSubType::BOTTOMCENTER:
+ pTransition->makeDissolve();
+ break;
+ }
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeFadeSmoothly();
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeFadeThroughBlack();
+ } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeDiamond();
+ } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeNewsflash();
+ }
+
+ rtl::Reference<OGLTransitionerImpl> xRes(
+ new OGLTransitionerImpl(pTransition) );
+ if( bGLXPresent ) {
+ if( !xRes->initWindowFromSlideShowView(view))
+ return uno::Reference< presentation::XTransition >();
+ xRes->setSlides(leavingBitmap,enteringBitmap);
+ }
+
+ return uno::Reference<presentation::XTransition>(xRes.get());
+ }
+};
+
+}
+
+namespace sdecl = comphelper::service_decl;
+#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+ sdecl::class_<OGLTransitionFactoryImpl> serviceImpl;
+ const sdecl::ServiceDecl OGLTransitionFactoryDecl(
+ serviceImpl,
+#else
+ const sdecl::ServiceDecl OGLTransitionFactoryDecl(
+ sdecl::class_<OGLTransitionFactoryImpl>(),
+#endif
+ "com.sun.star.comp.presentation.OGLTransitionFactory",
+ "com.sun.star.presentation.TransitionFactory" );
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(OGLTransitionFactoryDecl)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/OGLTrans/exports.dxp b/slideshow/source/engine/OGLTrans/exports.dxp
new file mode 100644
index 000000000000..9630d7e06768
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/exports.dxp
@@ -0,0 +1,3 @@
+component_getImplementationEnvironment
+component_writeInfo
+component_getFactory
diff --git a/slideshow/source/engine/OGLTrans/makefile.mk b/slideshow/source/engine/OGLTrans/makefile.mk
new file mode 100644
index 000000000000..dd945a06b1aa
--- /dev/null
+++ b/slideshow/source/engine/OGLTrans/makefile.mk
@@ -0,0 +1,80 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=slideshow
+TARGET=OGLTrans
+TARGETTYPE=GUI
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Nothing to do if we're compiling with --disable-opengl -----------
+.IF "$(ENABLE_OPENGL)" != "TRUE"
+@all:
+ @echo "Building without OpenGL Transitions..."
+.ENDIF
+
+# --- Common ----------------------------------------------------------
+#.IF "$(GUI)"=="UNX"
+
+SLOFILES = \
+ $(SLO)$/OGLTrans_TransitionImpl.obj \
+ $(SLO)$/OGLTrans_Shaders.obj \
+ $(SLO)$/OGLTrans_TransitionerImpl.obj
+
+DLLPRE=
+SHL1TARGET=$(TARGET).uno
+
+.IF "$(GUI)"=="UNX"
+.IF "$(GUIBASE)"=="aqua"
+ SHL1STDLIBS= $(SALLIB) $(VCLLIB) $(CPPULIB) $(CPPUHELPERLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB)
+ CFLAGSCXX+=$(OBJCXXFLAGS)
+.ELSE
+ SHL1STDLIBS= $(SALLIB) $(VCLLIB) $(CPPULIB) $(CPPUHELPERLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) -lGL -lGLU -lX11
+.ENDIF
+.ELSE
+ SHL1STDLIBS= $(SALLIB) $(VCLLIB) $(CPPULIB) $(CPPUHELPERLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) opengl32.lib glu32.lib gdi32.lib
+.ENDIF
+SHL1IMPLIB=i$(TARGET)
+SHL1LIBS=$(SLB)$/$(TARGET).lib
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+SHL1VERSIONMAP=$(SOLARENV)/src/component.map
+
+DEF1NAME=$(SHL1TARGET)
+DEF1EXPORTFILE=exports.dxp
+
+#.ENDIF
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/activities/accumulation.hxx b/slideshow/source/engine/activities/accumulation.hxx
new file mode 100644
index 000000000000..b8b317192021
--- /dev/null
+++ b/slideshow/source/engine/activities/accumulation.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ACCUMULATION_HXX
+#define INCLUDED_SLIDESHOW_ACCUMULATION_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Generic accumulation.
+
+ This template handles value accumulation across repeated
+ effect runs: returned is the end value times the repeat
+ count, plus the current value.
+
+ @param rEndValue
+ End value of the simple animation.
+
+ @param nRepeatCount
+ Number of completed repeats (i.e. 0 during the first
+ effect run)
+
+ @param rCurrValue
+ Current animation value
+ */
+ template< typename ValueType > ValueType accumulate( const ValueType& rEndValue,
+ sal_uInt32 nRepeatCount,
+ const ValueType& rCurrValue )
+ {
+ return nRepeatCount*rEndValue + rCurrValue;
+ }
+
+ /// Specialization for non-addable enums/constant values
+ template<> sal_Int16 accumulate< sal_Int16 >( const sal_Int16&,
+ sal_uInt32,
+ const sal_Int16& rCurrValue )
+ {
+ // always return rCurrValue, it's forbidden to add enums/constant values...
+ return rCurrValue;
+ }
+
+ /// Specialization for non-addable strings
+ template<> ::rtl::OUString accumulate< ::rtl::OUString >( const ::rtl::OUString&,
+ sal_uInt32,
+ const ::rtl::OUString& rCurrValue )
+ {
+ // always return rCurrValue, it's impossible to add strings...
+ return rCurrValue;
+ }
+
+ /// Specialization for non-addable bools
+ template<> bool accumulate< bool >( const bool&,
+ sal_uInt32,
+ const bool& bCurrValue )
+ {
+ // always return bCurrValue, SMIL spec requires to ignore
+ // cumulative behaviour for bools.
+ return bCurrValue;
+ }
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ACCUMULATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/activitiesfactory.cxx b/slideshow/source/engine/activities/activitiesfactory.cxx
new file mode 100644
index 000000000000..f42a6497f25b
--- /dev/null
+++ b/slideshow/source/engine/activities/activitiesfactory.cxx
@@ -0,0 +1,989 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/animations/AnimationCalcMode.hpp>
+#include <comphelper/sequence.hxx>
+
+#include "activitiesfactory.hxx"
+#include "smilfunctionparser.hxx"
+#include "accumulation.hxx"
+#include "activityparameters.hxx"
+#include "interpolation.hxx"
+#include "tools.hxx"
+#include "simplecontinuousactivitybase.hxx"
+#include "discreteactivitybase.hxx"
+#include "continuousactivitybase.hxx"
+#include "continuouskeytimeactivitybase.hxx"
+
+#include <boost/bind.hpp>
+#include <boost/optional.hpp>
+
+#include <cmath> // for modf
+#include <vector>
+#include <algorithm>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+/** Traits template, to take formula application only for ValueType = double
+ */
+template<typename ValueType> struct FormulaTraits
+{
+ static ValueType getPresentationValue(
+ const ValueType& rVal, const ExpressionNodeSharedPtr& )
+ {
+ return rVal;
+ }
+};
+
+/// Specialization for ValueType = double
+template<> struct FormulaTraits<double>
+{
+ static double getPresentationValue(
+ double const& rVal, ExpressionNodeSharedPtr const& rFormula )
+ {
+ return rFormula ? (*rFormula)(rVal) : rVal;
+ }
+};
+
+// Various ActivityBase specializations for different animator types
+// =================================================================
+
+/** FromToBy handler
+
+ Provides the Activity specializations for FromToBy
+ animations (e.g. those without a values list).
+
+ This template makes heavy use of SFINAE, only one of
+ the perform*() methods will compile for each of the
+ base classes.
+
+ Note that we omit the virtual keyword on the perform()
+ overrides on purpose; those that actually do override
+ baseclass virtual methods inherit the property, and
+ the others won't increase our vtable. What's more,
+ having all perform() method in the vtable actually
+ creates POIs for them, which breaks the whole SFINAE
+ concept (IOW, this template won't compile any longer).
+
+ @tpl BaseType
+ Base class to use for this activity. Only
+ ContinuousActivityBase and DiscreteActivityBase are
+ supported here.
+
+ @tpl AnimationType
+ Type of the Animation to call.
+*/
+template<class BaseType, typename AnimationType>
+class FromToByActivity : public BaseType
+{
+public:
+ typedef typename AnimationType::ValueType ValueType;
+ typedef boost::optional<ValueType> OptionalValueType;
+
+private:
+ // some compilers don't inline whose definition they haven't
+ // seen before the call site...
+ ValueType getPresentationValue( const ValueType& rVal ) const
+ {
+ return FormulaTraits<ValueType>::getPresentationValue( rVal, mpFormula);
+ }
+
+public:
+ /** Create FromToByActivity.
+
+ @param rFrom
+ From this value, the animation starts
+
+ @param rTo
+ With this value, the animation ends
+
+ @param rBy
+ With this value, the animation increments the start value
+
+ @param rParms
+ Standard Activity parameter struct
+
+ @param rAnim
+ Shared ptr to AnimationType
+
+ @param rInterpolator
+ Interpolator object to be used for lerping between
+ start and end value (need to be passed, since it
+ might contain state, e.g. interpolation direction
+ for HSL color space).
+
+ @param bCumulative
+ Whether repeated animations should cumulate the
+ value, or start fresh each time.
+ */
+ FromToByActivity(
+ const OptionalValueType& rFrom,
+ const OptionalValueType& rTo,
+ const OptionalValueType& rBy,
+ const ActivityParameters& rParms,
+ const ::boost::shared_ptr< AnimationType >& rAnim,
+ const Interpolator< ValueType >& rInterpolator,
+ bool bCumulative )
+ : BaseType( rParms ),
+ maFrom( rFrom ),
+ maTo( rTo ),
+ maBy( rBy ),
+ mpFormula( rParms.mpFormula ),
+ maStartValue(),
+ maEndValue(),
+ mpAnim( rAnim ),
+ maInterpolator( rInterpolator ),
+ mbDynamicStartValue( false ),
+ mbCumulative( bCumulative )
+ {
+ ENSURE_OR_THROW( mpAnim, "Invalid animation object" );
+
+ ENSURE_OR_THROW(
+ rTo || rBy,
+ "From and one of To or By, or To or By alone must be valid" );
+ }
+
+ virtual void startAnimation()
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ BaseType::startAnimation();
+
+ // start animation
+ mpAnim->start( BaseType::getShape(),
+ BaseType::getShapeAttributeLayer() );
+
+ // setup start and end value. Determine animation
+ // start value only when animation actually
+ // started up (this order is part of the Animation
+ // interface contract)
+ const ValueType aAnimationStartValue( mpAnim->getUnderlyingValue() );
+
+ // first of all, determine general type of
+ // animation, by inspecting which of the FromToBy values
+ // are actually valid.
+ // See http://www.w3.org/TR/smil20/animation.html#AnimationNS-FromToBy
+ // for a definition
+ if( maFrom )
+ {
+ // From-to or From-by animation. According to
+ // SMIL spec, the To value takes precedence
+ // over the By value, if both are specified
+ if( maTo )
+ {
+ // From-To animation
+ maStartValue = *maFrom;
+ maEndValue = *maTo;
+ }
+ else if( maBy )
+ {
+ // From-By animation
+ maStartValue = *maFrom;
+ maEndValue = maStartValue + *maBy;
+ }
+ }
+ else
+ {
+ // By or To animation. According to SMIL spec,
+ // the To value takes precedence over the By
+ // value, if both are specified
+ if( maTo )
+ {
+ // To animation
+
+ // According to the SMIL spec
+ // (http://www.w3.org/TR/smil20/animation.html#animationNS-ToAnimation),
+ // the to animation interpolates between
+ // the _running_ underlying value and the to value (as the end value)
+ mbDynamicStartValue = true;
+ maEndValue = *maTo;
+ }
+ else if( maBy )
+ {
+ // By animation
+ maStartValue = aAnimationStartValue;
+ maEndValue = maStartValue + *maBy;
+ }
+ }
+ }
+
+ virtual void endAnimation()
+ {
+ // end animation
+ if (mpAnim)
+ mpAnim->end();
+ }
+
+ /// perform override for ContinuousActivityBase
+ void perform( double nModifiedTime, sal_uInt32 nRepeatCount ) const
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ (*mpAnim)(
+ getPresentationValue(
+ accumulate( maEndValue,
+ mbCumulative * nRepeatCount, // means: mbCumulative ? nRepeatCount : 0,
+ maInterpolator( (mbDynamicStartValue
+ ? mpAnim->getUnderlyingValue()
+ : maStartValue),
+ maEndValue,
+ nModifiedTime ) ) ) );
+ }
+
+ using BaseType::perform;
+
+ /// perform override for DiscreteActivityBase base
+ void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ (*mpAnim)(
+ getPresentationValue(
+ accumulate( maEndValue, mbCumulative ? nRepeatCount : 0,
+ lerp( maInterpolator,
+ (mbDynamicStartValue
+ ? mpAnim->getUnderlyingValue()
+ : maStartValue),
+ maEndValue,
+ nFrame,
+ BaseType::getNumberOfKeyTimes() ) ) ) );
+ }
+
+ using BaseType::isAutoReverse;
+
+ virtual void performEnd()
+ {
+ // xxx todo: good guess
+ if (mpAnim)
+ {
+ if (isAutoReverse())
+ (*mpAnim)( getPresentationValue( maStartValue ) );
+ else
+ (*mpAnim)( getPresentationValue( maEndValue ) );
+ }
+ }
+
+ /// Disposable:
+ virtual void dispose()
+ {
+ mpAnim.reset();
+ BaseType::dispose();
+ }
+
+private:
+ const OptionalValueType maFrom;
+ const OptionalValueType maTo;
+ const OptionalValueType maBy;
+
+ ExpressionNodeSharedPtr mpFormula;
+
+ ValueType maStartValue;
+ ValueType maEndValue;
+
+ ::boost::shared_ptr< AnimationType > mpAnim;
+ Interpolator< ValueType > maInterpolator;
+ bool mbDynamicStartValue;
+ bool mbCumulative;
+};
+
+
+/** Generate Activity corresponding to given FromToBy values
+
+ @tpl BaseType
+ BaseType to use for deriving the Activity from
+
+ @tpl AnimationType
+ Subtype of the Animation object (e.g. NumberAnimation)
+*/
+template<class BaseType, typename AnimationType>
+AnimationActivitySharedPtr createFromToByActivity(
+ const uno::Any& rFromAny,
+ const uno::Any& rToAny,
+ const uno::Any& rByAny,
+ const ActivityParameters& rParms,
+ const ::boost::shared_ptr< AnimationType >& rAnim,
+ const Interpolator< typename AnimationType::ValueType >& rInterpolator,
+ bool bCumulative,
+ const ShapeSharedPtr& rShape,
+ const ::basegfx::B2DVector& rSlideBounds )
+{
+ typedef typename AnimationType::ValueType ValueType;
+ typedef boost::optional<ValueType> OptionalValueType;
+
+ OptionalValueType aFrom;
+ OptionalValueType aTo;
+ OptionalValueType aBy;
+
+ ValueType aTmpValue;
+
+ if( rFromAny.hasValue() )
+ {
+ ENSURE_OR_THROW(
+ extractValue( aTmpValue, rFromAny, rShape, rSlideBounds ),
+ "createFromToByActivity(): Could not extract from value" );
+ aFrom.reset(aTmpValue);
+ }
+ if( rToAny.hasValue() )
+ {
+ ENSURE_OR_THROW(
+ extractValue( aTmpValue, rToAny, rShape, rSlideBounds ),
+ "createFromToByActivity(): Could not extract to value" );
+ aTo.reset(aTmpValue);
+ }
+ if( rByAny.hasValue() )
+ {
+ ENSURE_OR_THROW(
+ extractValue( aTmpValue, rByAny, rShape, rSlideBounds ),
+ "createFromToByActivity(): Could not extract by value" );
+ aBy.reset(aTmpValue);
+ }
+
+ return AnimationActivitySharedPtr(
+ new FromToByActivity<BaseType, AnimationType>(
+ aFrom,
+ aTo,
+ aBy,
+ rParms,
+ rAnim,
+ rInterpolator,
+ bCumulative ) );
+}
+
+/* The following table shows which animator combines with
+ which Activity type:
+
+ NumberAnimator: all
+ PairAnimation: all
+ ColorAnimation: all
+ StringAnimation: DiscreteActivityBase
+ BoolAnimation: DiscreteActivityBase
+*/
+
+/** Values handler
+
+ Provides the Activity specializations for value lists
+ animations.
+
+ This template makes heavy use of SFINAE, only one of
+ the perform*() methods will compile for each of the
+ base classes.
+
+ Note that we omit the virtual keyword on the perform()
+ overrides on purpose; those that actually do override
+ baseclass virtual methods inherit the property, and
+ the others won't increase our vtable. What's more,
+ having all perform() method in the vtable actually
+ creates POIs for them, which breaks the whole SFINAE
+ concept (IOW, this template won't compile any longer).
+
+ @tpl BaseType
+ Base class to use for this activity. Only
+ ContinuousKeyTimeActivityBase and DiscreteActivityBase
+ are supported here. For values animation without key
+ times, the client must emulate key times by providing
+ a vector of equally spaced values between 0 and 1,
+ with the same number of entries as the values vector.
+
+ @tpl AnimationType
+ Type of the Animation to call.
+*/
+template<class BaseType, typename AnimationType>
+class ValuesActivity : public BaseType
+{
+public:
+ typedef typename AnimationType::ValueType ValueType;
+ typedef std::vector<ValueType> ValueVectorType;
+
+private:
+ // some compilers don't inline methods whose definition they haven't
+ // seen before the call site...
+ ValueType getPresentationValue( const ValueType& rVal ) const
+ {
+ return FormulaTraits<ValueType>::getPresentationValue(
+ rVal, mpFormula );
+ }
+
+public:
+ /** Create ValuesActivity.
+
+ @param rValues
+ Value vector to cycle animation through
+
+ @param rParms
+ Standard Activity parameter struct
+
+ @param rAnim
+ Shared ptr to AnimationType
+
+ @param rInterpolator
+ Interpolator object to be used for lerping between
+ start and end value (need to be passed, since it
+ might contain state, e.g. interpolation direction
+ for HSL color space).
+
+ @param bCumulative
+ Whether repeated animations should cumulate the
+ value, or start afresh each time.
+ */
+ ValuesActivity(
+ const ValueVectorType& rValues,
+ const ActivityParameters& rParms,
+ const boost::shared_ptr<AnimationType>& rAnim,
+ const Interpolator< ValueType >& rInterpolator,
+ bool bCumulative )
+ : BaseType( rParms ),
+ maValues( rValues ),
+ mpFormula( rParms.mpFormula ),
+ mpAnim( rAnim ),
+ maInterpolator( rInterpolator ),
+ mbCumulative( bCumulative )
+ {
+ ENSURE_OR_THROW( mpAnim, "Invalid animation object" );
+ ENSURE_OR_THROW( !rValues.empty(), "Empty value vector" );
+ }
+
+ virtual void startAnimation()
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ BaseType::startAnimation();
+
+ // start animation
+ mpAnim->start( BaseType::getShape(),
+ BaseType::getShapeAttributeLayer() );
+ }
+
+ virtual void endAnimation()
+ {
+ // end animation
+ if (mpAnim)
+ mpAnim->end();
+ }
+
+ /// perform override for ContinuousKeyTimeActivityBase base
+ void perform( sal_uInt32 nIndex,
+ double nFractionalIndex,
+ sal_uInt32 nRepeatCount ) const
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ ENSURE_OR_THROW( nIndex+1 < maValues.size(),
+ "ValuesActivity::perform(): index out of range" );
+
+ // interpolate between nIndex and nIndex+1 values
+ (*mpAnim)(
+ getPresentationValue(
+ accumulate( maValues.back(),
+ mbCumulative ? nRepeatCount : 0,
+ maInterpolator( maValues[ nIndex ],
+ maValues[ nIndex+1 ],
+ nFractionalIndex ) ) ) );
+ }
+
+ using BaseType::perform;
+
+ /// perform override for DiscreteActivityBase base
+ void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ ENSURE_OR_THROW( nFrame < maValues.size(),
+ "ValuesActivity::perform(): index out of range" );
+
+ // this is discrete, thus no lerp here.
+ (*mpAnim)(
+ getPresentationValue(
+ accumulate( maValues.back(),
+ mbCumulative ? nRepeatCount : 0,
+ maValues[ nFrame ] ) ) );
+ }
+
+ virtual void performEnd()
+ {
+ // xxx todo: good guess
+ if (mpAnim)
+ (*mpAnim)( getPresentationValue( maValues.back() ) );
+ }
+
+ /// Disposable:
+ virtual void dispose()
+ {
+ mpAnim.reset();
+ BaseType::dispose();
+ }
+
+private:
+ ValueVectorType maValues;
+
+ ExpressionNodeSharedPtr mpFormula;
+
+ boost::shared_ptr<AnimationType> mpAnim;
+ Interpolator< ValueType > maInterpolator;
+ bool mbCumulative;
+};
+
+/** Generate Activity corresponding to given Value vector
+
+ @tpl BaseType
+ BaseType to use for deriving the Activity from
+
+ @tpl AnimationType
+ Subtype of the Animation object (e.g. NumberAnimation)
+*/
+template<class BaseType, typename AnimationType>
+AnimationActivitySharedPtr createValueListActivity(
+ const uno::Sequence<uno::Any>& rValues,
+ const ActivityParameters& rParms,
+ const boost::shared_ptr<AnimationType>& rAnim,
+ const Interpolator<typename AnimationType::ValueType>& rInterpolator,
+ bool bCumulative,
+ const ShapeSharedPtr& rShape,
+ const ::basegfx::B2DVector& rSlideBounds )
+{
+ typedef typename AnimationType::ValueType ValueType;
+ typedef std::vector<ValueType> ValueVectorType;
+
+ ValueVectorType aValueVector;
+ aValueVector.reserve( rValues.getLength() );
+
+ for( ::std::size_t i=0, nLen=rValues.getLength(); i<nLen; ++i )
+ {
+ ValueType aValue;
+ ENSURE_OR_THROW(
+ extractValue( aValue, rValues[i], rShape, rSlideBounds ),
+ "createValueListActivity(): Could not extract values" );
+ aValueVector.push_back( aValue );
+ }
+
+ return AnimationActivitySharedPtr(
+ new ValuesActivity<BaseType, AnimationType>(
+ aValueVector,
+ rParms,
+ rAnim,
+ rInterpolator,
+ bCumulative ) );
+}
+
+/** Generate Activity for given XAnimate, corresponding to given Value vector
+
+ @tpl AnimationType
+ Subtype of the Animation object (e.g. NumberAnimation)
+
+ @param rParms
+ Common activity parameters
+
+ @param xNode
+ XAnimate node, to retrieve animation values from
+
+ @param rAnim
+ Actual animation to operate with (gets called with the
+ time-dependent values)
+
+ @param rInterpolator
+ Interpolator object to be used for lerping between
+ start and end values (need to be passed, since it
+ might contain state, e.g. interpolation direction
+ for HSL color space).
+*/
+template<typename AnimationType>
+AnimationActivitySharedPtr createActivity(
+ const ActivitiesFactory::CommonParameters& rParms,
+ const uno::Reference< animations::XAnimate >& xNode,
+ const ::boost::shared_ptr< AnimationType >& rAnim,
+ const Interpolator< typename AnimationType::ValueType >& rInterpolator
+ = Interpolator< typename AnimationType::ValueType >() )
+{
+ // setup common parameters
+ // =======================
+
+ ActivityParameters aActivityParms( rParms.mpEndEvent,
+ rParms.mrEventQueue,
+ rParms.mrActivitiesQueue,
+ rParms.mnMinDuration,
+ rParms.maRepeats,
+ rParms.mnAcceleration,
+ rParms.mnDeceleration,
+ rParms.mnMinNumberOfFrames,
+ rParms.mbAutoReverse );
+
+ // is a formula given?
+ const ::rtl::OUString& rFormulaString( xNode->getFormula() );
+ if( rFormulaString.getLength() )
+ {
+ // yep, parse and pass to ActivityParameters
+ try
+ {
+ aActivityParms.mpFormula =
+ SmilFunctionParser::parseSmilFunction(
+ rFormulaString,
+ calcRelativeShapeBounds(
+ rParms.maSlideBounds,
+ rParms.mpShape->getBounds() ) );
+ }
+ catch( ParseError& )
+ {
+ // parse error, thus no formula
+ OSL_ENSURE( false,
+ "createActivity(): Error parsing formula string" );
+ }
+ }
+
+ // are key times given?
+ const uno::Sequence< double >& aKeyTimes( xNode->getKeyTimes() );
+ if( aKeyTimes.hasElements() )
+ {
+ // yes, convert them from Sequence< double >
+ aActivityParms.maDiscreteTimes.resize( aKeyTimes.getLength() );
+ comphelper::sequenceToArray(
+ &aActivityParms.maDiscreteTimes[0],
+ aKeyTimes ); // saves us some temporary vectors
+ }
+
+ // values sequence given?
+ const sal_Int32 nValueLen( xNode->getValues().getLength() );
+ if( nValueLen )
+ {
+ // Value list activity
+ // ===================
+
+ // fake keytimes, if necessary
+ if( !aKeyTimes.hasElements() )
+ {
+ // create a dummy vector of key times,
+ // with aValues.getLength equally spaced entries.
+ for( sal_Int32 i=0; i<nValueLen; ++i )
+ aActivityParms.maDiscreteTimes.push_back( double(i)/nValueLen );
+ }
+
+ // determine type of animation needed here:
+ // Value list activities are possible with
+ // ContinuousKeyTimeActivityBase and DiscreteActivityBase
+ // specializations
+ const sal_Int16 nCalcMode( xNode->getCalcMode() );
+
+ switch( nCalcMode )
+ {
+ case animations::AnimationCalcMode::DISCRETE:
+ {
+ // since DiscreteActivityBase suspends itself
+ // between the frames, create a WakeupEvent for it.
+ aActivityParms.mpWakeupEvent.reset(
+ new WakeupEvent(
+ rParms.mrEventQueue.getTimer(),
+ rParms.mrActivitiesQueue ) );
+
+ AnimationActivitySharedPtr pActivity(
+ createValueListActivity< DiscreteActivityBase >(
+ xNode->getValues(),
+ aActivityParms,
+ rAnim,
+ rInterpolator,
+ xNode->getAccumulate(),
+ rParms.mpShape,
+ rParms.maSlideBounds ) );
+
+ // WakeupEvent and DiscreteActivityBase need circular
+ // references to the corresponding other object.
+ aActivityParms.mpWakeupEvent->setActivity( pActivity );
+
+ return pActivity;
+ }
+
+ default:
+ OSL_ENSURE( false, "createActivity(): unexpected case" );
+ // FALLTHROUGH intended
+ case animations::AnimationCalcMode::PACED:
+ // FALLTHROUGH intended
+ case animations::AnimationCalcMode::SPLINE:
+ // FALLTHROUGH intended
+ case animations::AnimationCalcMode::LINEAR:
+ return createValueListActivity< ContinuousKeyTimeActivityBase >(
+ xNode->getValues(),
+ aActivityParms,
+ rAnim,
+ rInterpolator,
+ xNode->getAccumulate(),
+ rParms.mpShape,
+ rParms.maSlideBounds );
+ }
+ }
+ else
+ {
+ // FromToBy activity
+ // =================
+
+ // determine type of animation needed here:
+ // FromToBy activities are possible with
+ // ContinuousActivityBase and DiscreteActivityBase
+ // specializations
+ const sal_Int16 nCalcMode( xNode->getCalcMode() );
+
+ switch( nCalcMode )
+ {
+ case animations::AnimationCalcMode::DISCRETE:
+ {
+ // fake keytimes, if necessary
+ if( !aKeyTimes.hasElements() )
+ {
+ // create a dummy vector of 2 key times
+ const ::std::size_t nLen( 2 );
+ for( ::std::size_t i=0; i<nLen; ++i )
+ aActivityParms.maDiscreteTimes.push_back( double(i)/nLen );
+ }
+
+ // since DiscreteActivityBase suspends itself
+ // between the frames, create a WakeupEvent for it.
+ aActivityParms.mpWakeupEvent.reset(
+ new WakeupEvent(
+ rParms.mrEventQueue.getTimer(),
+ rParms.mrActivitiesQueue ) );
+
+ AnimationActivitySharedPtr pActivity(
+ createFromToByActivity< DiscreteActivityBase >(
+ xNode->getFrom(),
+ xNode->getTo(),
+ xNode->getBy(),
+ aActivityParms,
+ rAnim,
+ rInterpolator,
+ xNode->getAccumulate(),
+ rParms.mpShape,
+ rParms.maSlideBounds ) );
+
+ // WakeupEvent and DiscreteActivityBase need circular
+ // references to the corresponding other object.
+ aActivityParms.mpWakeupEvent->setActivity( pActivity );
+
+ return pActivity;
+ }
+
+ default:
+ OSL_ENSURE( false, "createActivity(): unexpected case" );
+ // FALLTHROUGH intended
+ case animations::AnimationCalcMode::PACED:
+ // FALLTHROUGH intended
+ case animations::AnimationCalcMode::SPLINE:
+ // FALLTHROUGH intended
+ case animations::AnimationCalcMode::LINEAR:
+ return createFromToByActivity< ContinuousActivityBase >(
+ xNode->getFrom(),
+ xNode->getTo(),
+ xNode->getBy(),
+ aActivityParms,
+ rAnim,
+ rInterpolator,
+ xNode->getAccumulate(),
+ rParms.mpShape,
+ rParms.maSlideBounds );
+ }
+ }
+}
+
+/** Simple activity for ActivitiesFactory::createSimpleActivity
+
+ @tpl Direction
+ Determines direction of value generator. A 1 yields a
+ forward direction, starting with 0.0 and ending with
+ 1.0. A 0 yields a backward direction, starting with
+ 1.0 and ending with 0.0
+*/
+template<int Direction>
+class SimpleActivity : public ContinuousActivityBase
+{
+public:
+ /** Create SimpleActivity.
+
+ @param rParms
+ Standard Activity parameter struct
+ */
+ SimpleActivity( const ActivityParameters& rParms,
+ const NumberAnimationSharedPtr& rAnim ) :
+ ContinuousActivityBase( rParms ),
+ mpAnim( rAnim )
+ {
+ ENSURE_OR_THROW( mpAnim, "Invalid animation object" );
+ }
+
+ virtual void startAnimation()
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ ContinuousActivityBase::startAnimation();
+
+ // start animation
+ mpAnim->start( getShape(),
+ getShapeAttributeLayer() );
+ }
+
+ virtual void endAnimation()
+ {
+ // end animation
+ if (mpAnim)
+ mpAnim->end();
+ }
+
+ using SimpleContinuousActivityBase::perform;
+
+ /// perform override for ContinuousActivityBase
+ virtual void perform( double nModifiedTime, sal_uInt32 ) const
+ {
+ if (this->isDisposed() || !mpAnim)
+ return;
+ // no cumulation, simple [0,1] range
+ (*mpAnim)( 1.0 - Direction + nModifiedTime*(2.0*Direction - 1.0) );
+ }
+
+ virtual void performEnd()
+ {
+ // xxx todo: review
+ if (mpAnim)
+ (*mpAnim)( 1.0*Direction );
+ }
+
+ /// Disposable:
+ virtual void dispose()
+ {
+ mpAnim.reset();
+ ContinuousActivityBase::dispose();
+ }
+
+private:
+ NumberAnimationSharedPtr mpAnim;
+};
+
+} // anon namespace
+
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const NumberAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimate >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms, xNode, rAnim );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const EnumAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimate >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms, xNode, rAnim );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const ColorAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimate >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms, xNode, rAnim );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const HSLColorAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimateColor >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms,
+ uno::Reference< animations::XAnimate >(
+ xNode, uno::UNO_QUERY_THROW ),
+ rAnim,
+ // Direction==true means clockwise in SMIL API
+ Interpolator< HSLColor >( !xNode->getDirection() ) );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const PairAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimate >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms, xNode, rAnim );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const StringAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimate >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms, xNode, rAnim );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createAnimateActivity(
+ const CommonParameters& rParms,
+ const BoolAnimationSharedPtr& rAnim,
+ const uno::Reference< animations::XAnimate >& xNode )
+{
+ // forward to appropriate template instantiation
+ return createActivity( rParms, xNode, rAnim );
+}
+
+AnimationActivitySharedPtr ActivitiesFactory::createSimpleActivity(
+ const CommonParameters& rParms,
+ const NumberAnimationSharedPtr& rAnim,
+ bool bDirectionForward )
+{
+ ActivityParameters aActivityParms( rParms.mpEndEvent,
+ rParms.mrEventQueue,
+ rParms.mrActivitiesQueue,
+ rParms.mnMinDuration,
+ rParms.maRepeats,
+ rParms.mnAcceleration,
+ rParms.mnDeceleration,
+ rParms.mnMinNumberOfFrames,
+ rParms.mbAutoReverse );
+
+ if( bDirectionForward )
+ return AnimationActivitySharedPtr(
+ new SimpleActivity<1>( aActivityParms, rAnim ) );
+ else
+ return AnimationActivitySharedPtr(
+ new SimpleActivity<0>( aActivityParms, rAnim ) );
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/activitybase.cxx b/slideshow/source/engine/activities/activitybase.cxx
new file mode 100644
index 000000000000..541e6e9e7e7d
--- /dev/null
+++ b/slideshow/source/engine/activities/activitybase.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <activitybase.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ // TODO(P1): Elide some virtual function calls, by templifying this
+ // static hierarchy
+
+ ActivityBase::ActivityBase( const ActivityParameters& rParms ) :
+ mpEndEvent( rParms.mrEndEvent ),
+ mrEventQueue( rParms.mrEventQueue ),
+ mpShape(),
+ mpAttributeLayer(),
+ maRepeats( rParms.mrRepeats ),
+ mnAccelerationFraction( rParms.mnAccelerationFraction ),
+ mnDecelerationFraction( rParms.mnDecelerationFraction ),
+ mbAutoReverse( rParms.mbAutoReverse ),
+ mbFirstPerformCall( true ),
+ mbIsActive( true ) {}
+
+ void ActivityBase::dispose()
+ {
+ // deactivate
+ mbIsActive = false;
+
+ // dispose event
+ if( mpEndEvent )
+ mpEndEvent->dispose();
+
+ // release references
+ mpEndEvent.reset();
+ mpShape.reset();
+ mpAttributeLayer.reset();
+ }
+
+ double ActivityBase::calcTimeLag() const
+ {
+ // TODO(Q1): implement different init process!
+ if (isActive() && mbFirstPerformCall)
+ {
+ mbFirstPerformCall = false;
+
+ // notify derived classes that we're
+ // starting now
+ const_cast<ActivityBase *>(this)->startAnimation();
+ }
+ return 0.0;
+ }
+
+ bool ActivityBase::perform()
+ {
+ // still active?
+ if( !isActive() )
+ return false; // no, early exit.
+
+ OSL_ASSERT( ! mbFirstPerformCall );
+
+ return true;
+ }
+
+ bool ActivityBase::isActive() const
+ {
+ return mbIsActive;
+ }
+
+ void ActivityBase::setTargets( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+ {
+ ENSURE_OR_THROW( rShape,
+ "ActivityBase::setTargets(): Invalid shape" );
+ ENSURE_OR_THROW( rAttrLayer,
+ "ActivityBase::setTargets(): Invalid attribute layer" );
+
+ mpShape = rShape;
+ mpAttributeLayer = rAttrLayer;
+ }
+
+ void ActivityBase::endActivity()
+ {
+ // this is a regular activity end
+ mbIsActive = false;
+
+ // Activity is ending, queue event, then
+ if( mpEndEvent )
+ mrEventQueue.addEvent( mpEndEvent );
+
+ // release references
+ mpEndEvent.reset();
+ }
+
+ void ActivityBase::dequeued()
+ {
+ // xxx todo:
+// // ignored here, if we're still active. Discrete
+// // activities are dequeued after every perform() call,
+// // thus, the call is only significant when isActive() ==
+// // false.
+ if( !isActive() )
+ endAnimation();
+ }
+
+ void ActivityBase::end()
+ {
+ if (!isActive() || isDisposed())
+ return;
+ // assure animation is started:
+ if (mbFirstPerformCall) {
+ mbFirstPerformCall = false;
+ // notify derived classes that we're starting now
+ this->startAnimation();
+ }
+
+ performEnd(); // calling private virtual
+ endAnimation();
+ endActivity();
+ }
+
+ double ActivityBase::calcAcceleratedTime( double nT ) const
+ {
+ // Handle acceleration/deceleration
+ // ================================
+
+ // clamp nT to permissible [0,1] range
+ nT = ::basegfx::clamp( nT, 0.0, 1.0 );
+
+ // take acceleration/deceleration into account. if the sum
+ // of mnAccelerationFraction and mnDecelerationFraction
+ // exceeds 1.0, ignore both (that's according to SMIL spec)
+ if( (mnAccelerationFraction > 0.0 ||
+ mnDecelerationFraction > 0.0) &&
+ mnAccelerationFraction + mnDecelerationFraction <= 1.0 )
+ {
+ /*
+ // calc accelerated/decelerated time.
+ //
+ // We have three intervals:
+ // 1 [0,a]
+ // 2 [a,d]
+ // 3 [d,1] (with a and d being acceleration/deceleration
+ // fraction, resp.)
+ //
+ // The change rate during interval 1 is constantly
+ // increasing, reaching 1 at a. It then stays at 1,
+ // starting a linear decrease at d, ending with 0 at
+ // time 1. The integral of this function is the
+ // required new time nT'.
+ //
+ // As we arbitrarily assumed 1 as the upper value of
+ // the change rate, the integral must be normalized to
+ // reach nT'=1 at the end of the interval. This
+ // normalization constant is:
+ //
+ // c = 1 - 0.5a - 0.5d
+ //
+ // The integral itself then amounts to:
+ //
+ // 0.5 nT^2 / a + (nT-a) + (nT - 0.5 nT^2 / d)
+ //
+ // (where each of the three summands correspond to the
+ // three intervals above, and are applied only if nT
+ // has reached the corresponding interval)
+ //
+ // The graph of the change rate is a trapezoid:
+ //
+ // |
+ // 1| /--------------\
+ // | / \
+ // | / \
+ // | / \
+ // -----------------------------
+ // 0 a d 1
+ //
+ //*/
+ const double nC( 1.0 - 0.5*mnAccelerationFraction - 0.5*mnDecelerationFraction );
+
+ // this variable accumulates the new time value
+ double nTPrime(0.0);
+
+ if( nT < mnAccelerationFraction )
+ {
+ nTPrime += 0.5*nT*nT/mnAccelerationFraction; // partial first interval
+ }
+ else
+ {
+ nTPrime += 0.5*mnAccelerationFraction; // full first interval
+
+ if( nT <= 1.0-mnDecelerationFraction )
+ {
+ nTPrime += nT-mnAccelerationFraction; // partial second interval
+ }
+ else
+ {
+ nTPrime += 1.0 - mnAccelerationFraction - mnDecelerationFraction; // full second interval
+
+ const double nTRelative( nT - 1.0 + mnDecelerationFraction );
+
+ nTPrime += nTRelative - 0.5*nTRelative*nTRelative / mnDecelerationFraction;
+ }
+ }
+
+ // normalize, and assign to work variable
+ nT = nTPrime / nC;
+ }
+
+ return nT;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/activitybase.hxx b/slideshow/source/engine/activities/activitybase.hxx
new file mode 100644
index 000000000000..d521df1783fe
--- /dev/null
+++ b/slideshow/source/engine/activities/activitybase.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ACTIVITYBASE_HXX
+#define INCLUDED_SLIDESHOW_ACTIVITYBASE_HXX
+
+#include "animationactivity.hxx"
+#include "activityparameters.hxx"
+#include "animatableshape.hxx"
+#include "shapeattributelayer.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** Base class for animation activities.
+
+ This whole class hierarchy is only for code sharing
+ between the various specializations (with or without
+ key times, fully discrete, etc.).
+*/
+class ActivityBase : public AnimationActivity
+{
+public:
+ ActivityBase( const ActivityParameters& rParms );
+
+ /// From Disposable interface
+ virtual void dispose();
+
+protected:
+ /** From Activity interface
+
+ Derived classes should override, call this first
+ and then perform their work.
+ */
+ virtual bool perform();
+ virtual double calcTimeLag() const;
+ virtual bool isActive() const;
+
+private:
+ virtual void dequeued();
+
+ // From AnimationActivity interface
+ virtual void setTargets(
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer );
+
+private:
+ /** Hook for derived classes
+
+ This method will be called from the first
+ perform() invocation, to signal the start of the
+ activity.
+ */
+ virtual void startAnimation() = 0;
+
+ /** Hook for derived classes
+
+ This method will be called after the last perform()
+ invocation, and after the potential changes of that
+ perform() call are committed to screen. That is, in
+ endAnimation(), the animation objects (sprites,
+ animation) can safely be destroyed, without causing
+ visible artifacts on screen.
+ */
+ virtual void endAnimation() = 0;
+
+protected:
+
+ /** End this activity, in a regular way.
+
+ This method is for derived classes needing to signal a
+ regular activity end (i.e. because the regular
+ duration is over)
+ */
+ void endActivity();
+
+ /** Modify fractional time.
+
+ This method modifies the fractional time (total
+ duration mapped to the [0,1] range) to the
+ effective simple time, but only according to
+ acceleration/deceleration.
+ */
+ double calcAcceleratedTime( double nT ) const;
+
+ bool isDisposed() const {
+ return (!mbIsActive && !mpEndEvent && !mpShape &&
+ !mpAttributeLayer);
+ }
+
+ EventQueue& getEventQueue() const { return mrEventQueue; }
+
+ AnimatableShapeSharedPtr getShape() const { return mpShape; }
+
+ ShapeAttributeLayerSharedPtr getShapeAttributeLayer() const
+ { return mpAttributeLayer; }
+
+ bool isRepeatCountValid() const { return maRepeats; }
+ double getRepeatCount() const { return *maRepeats; }
+ bool isAutoReverse() const { return mbAutoReverse; }
+
+private:
+ /// Activity:
+ virtual void end();
+ virtual void performEnd() = 0;
+
+private:
+ EventSharedPtr mpEndEvent;
+ EventQueue& mrEventQueue;
+ AnimatableShapeSharedPtr mpShape; // only to pass on to animation
+ ShapeAttributeLayerSharedPtr mpAttributeLayer; // only to pass on to anim
+
+ ::boost::optional<double> const maRepeats;
+ const double mnAccelerationFraction;
+ const double mnDecelerationFraction;
+
+ const bool mbAutoReverse;
+
+ // true, if perform() has not yet been called:
+ mutable bool mbFirstPerformCall;
+ bool mbIsActive;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_ACTIVITYBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/activityparameters.hxx b/slideshow/source/engine/activities/activityparameters.hxx
new file mode 100644
index 000000000000..0bab1359e9c4
--- /dev/null
+++ b/slideshow/source/engine/activities/activityparameters.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ACTIVITYPARAMETERS_HXX
+#define INCLUDED_SLIDESHOW_ACTIVITYPARAMETERS_HXX
+
+#include "event.hxx"
+#include "eventqueue.hxx"
+#include "expressionnode.hxx"
+#include "wakeupevent.hxx"
+
+#include <boost/optional.hpp>
+#include <vector>
+
+namespace slideshow {
+namespace internal {
+
+/** Parameter struct for animation activities
+
+ This struct contains all common parameters needed to
+ initialize the activities generated by the ActivityFactory.
+*/
+struct ActivityParameters
+{
+ /** Create
+
+ @param rEndEvent
+ Event to be fired, when the activity ends.
+
+ @param rEventQueue
+ Queue to add end event to
+
+ @param nMinDuration
+ Minimal duration of the activity (might actually be
+ longer because of nMinNumberOfFrames). Note that this
+ duration must always be the <em>simple</em> duration,
+ i.e. without any repeat.
+
+ @param rRepeats
+ Number of repeats. If this parameter is invalid,
+ infinite repeat is assumed.
+
+ @param nAccelerationFraction
+ Value between 0 and 1, denoting the fraction of the
+ total simple duration, which the animation should
+ accelerate.
+
+ @param nDecelerationFraction
+ Value between 0 and 1, denoting the fraction of the
+ total simple duration, which the animation should
+ decelerate. Note that the ranges
+ [0,nAccelerationFraction] and
+ [nDecelerationFraction,1] must be non-overlapping!
+
+ @param bAutoReverse
+ When true, at the end of the simple duration, the
+ animation plays reversed to the start value. Note that
+ nMinDuration still specifies the simple duration,
+ i.e. when bAutoReverse is true, the implicit duration
+ doubles.
+ */
+ ActivityParameters(
+ const EventSharedPtr& rEndEvent,
+ EventQueue& rEventQueue,
+ ActivitiesQueue& rActivitiesQueue,
+ double nMinDuration,
+ ::boost::optional<double> const& rRepeats,
+ double nAccelerationFraction,
+ double nDecelerationFraction,
+ sal_uInt32 nMinNumberOfFrames,
+ bool bAutoReverse )
+ : mrEndEvent( rEndEvent ),
+ mpWakeupEvent(),
+ mrEventQueue( rEventQueue ),
+ mrActivitiesQueue( rActivitiesQueue ),
+ mpFormula(),
+ maDiscreteTimes(),
+ mnMinDuration( nMinDuration ),
+ mrRepeats( rRepeats ),
+ mnAccelerationFraction( nAccelerationFraction ),
+ mnDecelerationFraction( nDecelerationFraction ),
+ mnMinNumberOfFrames( nMinNumberOfFrames ),
+ mbAutoReverse( bAutoReverse ) {}
+
+ /// End event to fire, when activity is over
+ const EventSharedPtr& mrEndEvent;
+ /// Wakeup event to use for discrete activities
+ WakeupEventSharedPtr mpWakeupEvent;
+
+ /// EventQueue to add events to
+ EventQueue& mrEventQueue;
+
+ /// ActivitiesQueue to add events to
+ ActivitiesQueue& mrActivitiesQueue;
+
+ /// Optional formula
+ ExpressionNodeSharedPtr mpFormula;
+
+ /// Key times, for discrete and key time activities
+ ::std::vector< double > maDiscreteTimes;
+
+ /// Total duration of activity (including all repeats)
+ const double mnMinDuration;
+ ::boost::optional<double> const& mrRepeats;
+ const double mnAccelerationFraction;
+ const double mnDecelerationFraction;
+
+ /// Minimal number of frames this activity must render
+ const sal_uInt32 mnMinNumberOfFrames;
+
+ /// When true, activity is played reversed after mnDuration.
+ const bool mbAutoReverse;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_ACTIVITYPARAMETERS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/continuousactivitybase.cxx b/slideshow/source/engine/activities/continuousactivitybase.cxx
new file mode 100644
index 000000000000..e6129d77af0c
--- /dev/null
+++ b/slideshow/source/engine/activities/continuousactivitybase.cxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <continuousactivitybase.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ContinuousActivityBase::ContinuousActivityBase( const ActivityParameters& rParms ) :
+ SimpleContinuousActivityBase( rParms )
+ {
+ }
+
+ void ContinuousActivityBase::simplePerform( double nSimpleTime,
+ sal_uInt32 nRepeatCount ) const
+ {
+ perform( calcAcceleratedTime( nSimpleTime ),
+ nRepeatCount );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/continuousactivitybase.hxx b/slideshow/source/engine/activities/continuousactivitybase.hxx
new file mode 100644
index 000000000000..6ef84dd0e7e7
--- /dev/null
+++ b/slideshow/source/engine/activities/continuousactivitybase.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_CONTINUOUSACTIVITYBASE_HXX
+#define INCLUDED_SLIDESHOW_CONTINUOUSACTIVITYBASE_HXX
+
+#include "simplecontinuousactivitybase.hxx"
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Simple, continuous animation.
+
+ This class implements a simple, continuous
+ animation. Only addition to ActivityBase class is an
+ explicit animation duration and a minimal number of
+ frames to display.
+ */
+ class ContinuousActivityBase : public SimpleContinuousActivityBase
+ {
+ public:
+ ContinuousActivityBase( const ActivityParameters& rParms );
+
+ using SimpleContinuousActivityBase::perform;
+
+ /** Hook for derived classes
+
+ This method will be called from perform(), already
+ equipped with the modified time (nMinNumberOfFrames, repeat,
+ acceleration and deceleration taken into account).
+
+ @param nModifiedTime
+ Already accelerated/decelerated and repeated time, always
+ in the [0,1] range.
+
+ @param nRepeatCount
+ Number of full repeats already performed
+ */
+ virtual void perform( double nModifiedTime, sal_uInt32 nRepeatCount ) const = 0;
+
+ /// From SimpleContinuousActivityBase class
+ virtual void simplePerform( double nSimpleTime,
+ sal_uInt32 nRepeatCount ) const;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_CONTINUOUSACTIVITYBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/continuouskeytimeactivitybase.cxx b/slideshow/source/engine/activities/continuouskeytimeactivitybase.cxx
new file mode 100644
index 000000000000..78b5b6f442c3
--- /dev/null
+++ b/slideshow/source/engine/activities/continuouskeytimeactivitybase.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <continuouskeytimeactivitybase.hxx>
+
+#include <boost/tuple/tuple.hpp>
+#include <algorithm>
+#include <iterator>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ContinuousKeyTimeActivityBase::ContinuousKeyTimeActivityBase( const ActivityParameters& rParms ) :
+ SimpleContinuousActivityBase( rParms ),
+ maLerper( rParms.maDiscreteTimes )
+ {
+ ENSURE_OR_THROW( rParms.maDiscreteTimes.size() > 1,
+ "ContinuousKeyTimeActivityBase::ContinuousKeyTimeActivityBase(): key times vector must have two entries or more" );
+ ENSURE_OR_THROW( rParms.maDiscreteTimes.front() == 0.0,
+ "ContinuousKeyTimeActivityBase::ContinuousKeyTimeActivityBase(): key times vector first entry must be zero" );
+ ENSURE_OR_THROW( rParms.maDiscreteTimes.back() <= 1.0,
+ "ContinuousKeyTimeActivityBase::ContinuousKeyTimeActivityBase(): key times vector last entry must be less or equal 1" );
+ }
+
+ void ContinuousKeyTimeActivityBase::simplePerform( double nSimpleTime,
+ sal_uInt32 nRepeatCount ) const
+ {
+ // calc simple time from global time - sweep through the
+ // array multiple times for repeated animations (according to
+ // SMIL spec).
+ double fAlpha( calcAcceleratedTime( nSimpleTime ) );
+ std::ptrdiff_t nIndex;
+
+ boost::tuples::tie(nIndex,fAlpha) = maLerper.lerp(fAlpha);
+
+ perform(
+ nIndex,
+ fAlpha,
+ nRepeatCount );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/continuouskeytimeactivitybase.hxx b/slideshow/source/engine/activities/continuouskeytimeactivitybase.hxx
new file mode 100644
index 000000000000..427fea36b2b8
--- /dev/null
+++ b/slideshow/source/engine/activities/continuouskeytimeactivitybase.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_CONTINUOUSKEYTIMEACTIVITYBASE_HXX
+#define INCLUDED_SLIDESHOW_CONTINUOUSKEYTIMEACTIVITYBASE_HXX
+
+#include "simplecontinuousactivitybase.hxx"
+
+#include <basegfx/tools/keystoplerp.hxx>
+#include <vector>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interpolated, key-times animation.
+
+ This class implements an interpolated key-times
+ animation, with continuous time.
+ */
+ class ContinuousKeyTimeActivityBase : public SimpleContinuousActivityBase
+ {
+ public:
+ ContinuousKeyTimeActivityBase( const ActivityParameters& rParms );
+
+ using SimpleContinuousActivityBase::perform;
+
+ /** Hook for derived classes
+
+ This method will be called from perform(), already
+ equipped with the modified time (nMinNumberOfFrames, repeat,
+ acceleration and deceleration taken into account).
+
+ @param nIndex
+ Current index of the key times/key values.
+
+ @param nFractionalIndex
+ Fractional value from the [0,1] range, specifying
+ the position between nIndex and nIndex+1.
+
+ @param nRepeatCount
+ Number of full repeats already performed
+ */
+ virtual void perform( sal_uInt32 nIndex,
+ double nFractionalIndex,
+ sal_uInt32 nRepeatCount ) const = 0;
+
+ /// From SimpleContinuousActivityBase class
+ virtual void simplePerform( double nSimpleTime,
+ sal_uInt32 nRepeatCount ) const;
+
+ private:
+ const ::basegfx::tools::KeyStopLerp maLerper;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_CONTINUOUSKEYTIMEACTIVITYBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/discreteactivitybase.cxx b/slideshow/source/engine/activities/discreteactivitybase.cxx
new file mode 100644
index 000000000000..949f0c8a8c27
--- /dev/null
+++ b/slideshow/source/engine/activities/discreteactivitybase.cxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <discreteactivitybase.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ DiscreteActivityBase::DiscreteActivityBase( const ActivityParameters& rParms ) :
+ ActivityBase( rParms ),
+ mpWakeupEvent( rParms.mpWakeupEvent ),
+ maDiscreteTimes( rParms.maDiscreteTimes ),
+ mnSimpleDuration( rParms.mnMinDuration ),
+ mnCurrPerformCalls( 0 )
+ {
+ ENSURE_OR_THROW( mpWakeupEvent,
+ "DiscreteActivityBase::DiscreteActivityBase(): Invalid wakeup event" );
+
+ ENSURE_OR_THROW( !maDiscreteTimes.empty(),
+ "DiscreteActivityBase::DiscreteActivityBase(): time vector is empty, why do you create me?" );
+
+#ifdef DBG_UTIL
+ // check parameters: rDiscreteTimes must be sorted in
+ // ascending order, and contain values only from the range
+ // [0,1]
+ for( ::std::size_t i=1, len=maDiscreteTimes.size(); i<len; ++i )
+ {
+ if( maDiscreteTimes[i] < 0.0 ||
+ maDiscreteTimes[i] > 1.0 ||
+ maDiscreteTimes[i-1] < 0.0 ||
+ maDiscreteTimes[i-1] > 1.0 )
+ {
+ ENSURE_OR_THROW( false, "DiscreteActivityBase::DiscreteActivityBase(): time values not within [0,1] range!" );
+ }
+
+ if( maDiscreteTimes[i-1] > maDiscreteTimes[i] )
+ ENSURE_OR_THROW( false, "DiscreteActivityBase::DiscreteActivityBase(): time vector is not sorted in ascending order!" );
+ }
+
+ // TODO(E2): check this also in production code?
+#endif
+ }
+
+ void DiscreteActivityBase::startAnimation()
+ {
+ // start timer on wakeup event
+ mpWakeupEvent->start();
+ }
+
+ sal_uInt32 DiscreteActivityBase::calcFrameIndex( sal_uInt32 nCurrCalls,
+ ::std::size_t nVectorSize ) const
+ {
+ if( isAutoReverse() )
+ {
+ // every full repeat run consists of one
+ // forward and one backward traversal.
+ sal_uInt32 nFrameIndex( nCurrCalls % (2*nVectorSize) );
+
+ // nFrameIndex values >= nVectorSize belong to
+ // the backward traversal
+ if( nFrameIndex >= nVectorSize )
+ nFrameIndex = 2*nVectorSize - nFrameIndex; // invert sweep
+
+ return nFrameIndex;
+ }
+ else
+ {
+ return nCurrCalls % nVectorSize ;
+ }
+ }
+
+ sal_uInt32 DiscreteActivityBase::calcRepeatCount( sal_uInt32 nCurrCalls,
+ ::std::size_t nVectorSize ) const
+ {
+ if( isAutoReverse() )
+ return nCurrCalls / (2*nVectorSize); // we've got 2 cycles per repeat
+ else
+ return nCurrCalls / nVectorSize;
+ }
+
+ bool DiscreteActivityBase::perform()
+ {
+ // call base class, for start() calls and end handling
+ if( !ActivityBase::perform() )
+ return false; // done, we're ended
+
+ const ::std::size_t nVectorSize( maDiscreteTimes.size() );
+
+ // actually perform something
+ // ==========================
+
+ // TODO(Q3): Refactor this mess
+
+ // call derived class with current frame index (modulo
+ // vector size, to cope with repeats)
+ perform( calcFrameIndex( mnCurrPerformCalls, nVectorSize ),
+ calcRepeatCount( mnCurrPerformCalls, nVectorSize ) );
+
+ // calc next index
+ ++mnCurrPerformCalls;
+
+ // calc currently reached repeat count
+ double nCurrRepeat( double(mnCurrPerformCalls) / nVectorSize );
+
+ // if auto-reverse is specified, halve the
+ // effective repeat count, since we pass every
+ // repeat run twice: once forward, once backward.
+ if( isAutoReverse() )
+ nCurrRepeat /= 2.0;
+
+ // schedule next frame, if either repeat is indefinite
+ // (repeat forever), or we've not yet reached the requested
+ // repeat count
+ if( !isRepeatCountValid() ||
+ nCurrRepeat < getRepeatCount() )
+ {
+ // add wake-up event to queue (modulo
+ // vector size, to cope with repeats).
+
+ // repeat is handled locally, only apply acceleration/deceleration.
+ // Scale time vector with simple duration, offset with full repeat
+ // times.
+ //
+ // Somewhat condensed, the argument for setNextTimeout below could
+ // be written as
+ //
+ // mnSimpleDuration*(nFullRepeats + calcAcceleratedTime( currentRepeatTime )),
+ //
+ // with currentRepeatTime = maDiscreteTimes[ currentRepeatIndex ]
+ //
+ // Note that calcAcceleratedTime() is only applied to the current repeat's value,
+ // not to the total resulting time. This is in accordance with the SMIL spec.
+ //
+ mpWakeupEvent->setNextTimeout(
+ mnSimpleDuration*(
+ calcRepeatCount(
+ mnCurrPerformCalls,
+ nVectorSize ) +
+ calcAcceleratedTime(
+ maDiscreteTimes[
+ calcFrameIndex(
+ mnCurrPerformCalls,
+ nVectorSize ) ] ) ) );
+
+ getEventQueue().addEvent( mpWakeupEvent );
+ }
+ else
+ {
+ // release event reference (relation to wakeup event
+ // is circular!)
+ mpWakeupEvent.reset();
+
+ // done with this activity
+ endActivity();
+ }
+
+ return false; // remove from queue, will be added back by the wakeup event.
+ }
+
+ void DiscreteActivityBase::dispose()
+ {
+ // dispose event
+ if( mpWakeupEvent )
+ mpWakeupEvent->dispose();
+
+ // release references
+ mpWakeupEvent.reset();
+
+ ActivityBase::dispose();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/discreteactivitybase.hxx b/slideshow/source/engine/activities/discreteactivitybase.hxx
new file mode 100644
index 000000000000..de4c11aeedc7
--- /dev/null
+++ b/slideshow/source/engine/activities/discreteactivitybase.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DISCRETEACTIVITYBASE_HXX
+#define INCLUDED_SLIDESHOW_DISCRETEACTIVITYBASE_HXX
+
+#include "activitybase.hxx"
+#include "wakeupevent.hxx"
+
+#include <vector>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Specialization of ActivityBase for discrete time activities.
+
+ A discrete time activity is one where time proceeds in
+ discrete steps, i.e. at given time instants.
+ */
+ class DiscreteActivityBase : public ActivityBase
+ {
+ public:
+ DiscreteActivityBase( const ActivityParameters& rParms );
+
+ /** Hook for derived classes.
+
+ This method is called for each discrete time
+ instant, with nFrame denoting the frame number
+ (starting with 0)
+
+ @param nFrame
+ Current frame number.
+
+ @param nRepeatCount
+ Number of full repeats already performed
+ */
+ virtual void perform( sal_uInt32 nFrame, sal_uInt32 nRepeatCount ) const = 0;
+ virtual void dispose();
+ virtual bool perform();
+
+ protected:
+ virtual void startAnimation();
+
+ sal_uInt32 calcFrameIndex( sal_uInt32 nCurrCalls,
+ ::std::size_t nVectorSize ) const;
+
+ sal_uInt32 calcRepeatCount( sal_uInt32 nCurrCalls,
+ ::std::size_t nVectorSize ) const;
+
+ ::std::size_t getNumberOfKeyTimes() const { return maDiscreteTimes.size(); }
+
+ private:
+ WakeupEventSharedPtr mpWakeupEvent;
+ const ::std::vector< double > maDiscreteTimes;
+ const double mnSimpleDuration;
+ sal_uInt32 mnCurrPerformCalls;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_DISCRETEACTIVITYBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/interpolation.hxx b/slideshow/source/engine/activities/interpolation.hxx
new file mode 100644
index 000000000000..5efa0f01527f
--- /dev/null
+++ b/slideshow/source/engine/activities/interpolation.hxx
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_INTERPOLATION_HXX
+#define INCLUDED_SLIDESHOW_INTERPOLATION_HXX
+
+#include <basegfx/tools/lerp.hxx>
+
+namespace basegfx
+{
+ namespace tools
+ {
+ // Interpolator specializations
+ // ============================
+
+ // NOTE: generic lerp is included from lerp.hxx. Following
+ // are some specializations for various
+ // not-straight-forward-interpolatable types
+
+ /// Specialization for RGBColor, to employ color-specific interpolator
+ template<> ::slideshow::internal::RGBColor lerp< ::slideshow::internal::RGBColor >(
+ const ::slideshow::internal::RGBColor& rFrom,
+ const ::slideshow::internal::RGBColor& rTo,
+ double t )
+ {
+ return interpolate( rFrom, rTo, t );
+ }
+
+ /// Specialization also for sal_Int16, although this code should not be called
+ template<> sal_Int16 lerp< sal_Int16 >( const sal_Int16&,
+ const sal_Int16& rTo,
+ double )
+ {
+ OSL_ENSURE( false,
+ "lerp<sal_Int16> called" );
+ return rTo;
+ }
+
+ /// Specialization also for string, although this code should not be called
+ template<> ::rtl::OUString lerp< ::rtl::OUString >( const ::rtl::OUString&,
+ const ::rtl::OUString& rTo,
+ double )
+ {
+ OSL_ENSURE( false,
+ "lerp<::rtl::OUString> called" );
+ return rTo;
+ }
+
+ /// Specialization also for bool, although this code should not be called
+ template<> bool lerp< bool >( const bool&,
+ const bool& rTo,
+ double )
+ {
+ OSL_ENSURE( false,
+ "lerp<bool> called" );
+ return rTo;
+ }
+ }
+}
+
+namespace slideshow
+{
+ namespace internal
+ {
+ template< typename ValueType > struct Interpolator
+ {
+ ValueType operator()( const ValueType& rFrom,
+ const ValueType& rTo,
+ double t ) const
+ {
+ return basegfx::tools::lerp( rFrom, rTo, t );
+ }
+ };
+
+ /// Specialization for HSLColor, to employ color-specific interpolator
+ template<> struct Interpolator< HSLColor >
+ {
+ Interpolator( bool bCCW ) :
+ mbCCW( bCCW )
+ {
+ }
+
+ HSLColor operator()( const HSLColor& rFrom,
+ const HSLColor& rTo,
+ double t ) const
+ {
+ return interpolate( rFrom, rTo, t, mbCCW );
+ }
+
+ private:
+ /// When true: interpolate counter-clockwise
+ const bool mbCCW;
+ };
+
+
+ /** Generic linear interpolator
+
+ @tpl ValueType
+ Must have operator+ and operator* defined, and should
+ have value semantics.
+
+ @param rInterpolator
+ Interpolator to use for lerp
+
+ @param nFrame
+ Must be in the [0,nTotalFrames) range
+
+ @param nTotalFrames
+ Total number of frames. Should be greater than zero.
+ */
+ template< typename ValueType > ValueType lerp( const Interpolator< ValueType >& rInterpolator,
+ const ValueType& rFrom,
+ const ValueType& rTo,
+ sal_uInt32 nFrame,
+ ::std::size_t nTotalFrames )
+ {
+ // TODO(P1): There's a nice HAKMEM trick for that
+ // nTotalFrames > 1 condition below
+
+ // for 1 and 0 frame animations, always take end value
+ const double nFraction( nTotalFrames > 1 ? double(nFrame)/(nTotalFrames-1) : 1.0 );
+
+ return rInterpolator( rFrom, rTo, nFraction );
+ }
+
+ /// Specialization for non-interpolatable constants/enums
+ template<> sal_Int16 lerp< sal_Int16 >( const Interpolator< sal_Int16 >& /*rInterpolator*/,
+ const sal_Int16& rFrom,
+ const sal_Int16& rTo,
+ sal_uInt32 nFrame,
+ ::std::size_t nTotalFrames )
+ {
+ // until one half of the total frames are over, take from value.
+ // after that, take to value.
+ // For nFrames not divisable by 2, we prefer to over from, which
+ // also neatly yields to for 1 frame activities
+ return nFrame < nTotalFrames/2 ? rFrom : rTo;
+ }
+
+ /// Specialization for non-interpolatable strings
+ template<> ::rtl::OUString lerp< ::rtl::OUString >( const Interpolator< ::rtl::OUString >& /*rInterpolator*/,
+ const ::rtl::OUString& rFrom,
+ const ::rtl::OUString& rTo,
+ sal_uInt32 nFrame,
+ ::std::size_t nTotalFrames )
+ {
+ // until one half of the total frames are over, take from value.
+ // after that, take to value.
+ // For nFrames not divisable by 2, we prefer to over from, which
+ // also neatly yields to for 1 frame activities
+ return nFrame < nTotalFrames/2 ? rFrom : rTo;
+ }
+
+ /// Specialization for non-interpolatable bools
+ template<> bool lerp< bool >( const Interpolator< bool >& /*rInterpolator*/,
+ const bool& bFrom,
+ const bool& bTo,
+ sal_uInt32 nFrame,
+ ::std::size_t nTotalFrames )
+ {
+ // until one half of the total frames are over, take from value.
+ // after that, take to value.
+ // For nFrames not divisable by 2, we prefer to over from, which
+ // also neatly yields to for 1 frame activities
+ return nFrame < nTotalFrames/2 ? bFrom : bTo;
+ }
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_INTERPOLATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/makefile.mk b/slideshow/source/engine/activities/makefile.mk
new file mode 100644
index 000000000000..fc24b4042265
--- /dev/null
+++ b/slideshow/source/engine/activities/makefile.mk
@@ -0,0 +1,53 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=slideshow
+TARGET=activities
+ENABLE_EXCEPTIONS=TRUE
+PRJINC=..$/..
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Common ----------------------------------------------------------
+
+SLOFILES = $(SLO)$/activitybase.obj \
+ $(SLO)$/activitiesfactory.obj \
+ $(SLO)$/continuousactivitybase.obj \
+ $(SLO)$/continuouskeytimeactivitybase.obj \
+ $(SLO)$/discreteactivitybase.obj \
+ $(SLO)$/simplecontinuousactivitybase.obj
+
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx b/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx
new file mode 100644
index 000000000000..e391a0fdb3a6
--- /dev/null
+++ b/slideshow/source/engine/activities/simplecontinuousactivitybase.cxx
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <simplecontinuousactivitybase.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ SimpleContinuousActivityBase::SimpleContinuousActivityBase(
+ const ActivityParameters& rParms ) :
+ ActivityBase( rParms ),
+ maTimer( rParms.mrActivitiesQueue.getTimer() ),
+ mnMinSimpleDuration( rParms.mnMinDuration ),
+ mnMinNumberOfFrames( rParms.mnMinNumberOfFrames ),
+ mnCurrPerformCalls( 0 )
+ {
+ }
+
+ void SimpleContinuousActivityBase::startAnimation()
+ {
+ // init timer. We measure animation time only when we're
+ // actually started.
+ maTimer.reset();
+ }
+
+ double SimpleContinuousActivityBase::calcTimeLag() const
+ {
+ ActivityBase::calcTimeLag();
+ if (! isActive())
+ return 0.0;
+
+ // retrieve locally elapsed time
+ const double nCurrElapsedTime( maTimer.getElapsedTime() );
+
+ // log time
+ VERBOSE_TRACE( "SimpleContinuousActivityBase::calcTimeLag(): "
+ "next step is based on time: %f", nCurrElapsedTime );
+
+ // go to great length to ensure a proper animation
+ // run. Since we don't know how often we will be called
+ // here, try to spread the animator calls uniquely over
+ // the [0,1] parameter range. Be aware of the fact that
+ // perform will be called at least mnMinNumberOfTurns
+ // times.
+
+ // fraction of time elapsed
+ const double nFractionElapsedTime(
+ nCurrElapsedTime / mnMinSimpleDuration );
+
+ // fraction of minimum calls performed
+ const double nFractionRequiredCalls(
+ double(mnCurrPerformCalls) / mnMinNumberOfFrames );
+
+ // okay, so now, the decision is easy:
+ //
+ // If the fraction of time elapsed is smaller than the
+ // number of calls required to be performed, then we calc
+ // the position on the animation range according to
+ // elapsed time. That is, we're so to say ahead of time.
+ //
+ // In contrary, if the fraction of time elapsed is larger,
+ // then we're lagging, and we thus calc the position on
+ // the animation time line according to the fraction of
+ // calls performed. Thus, the animation is forced to slow
+ // down, and take the required minimal number of steps,
+ // sufficiently equally distributed across the animation
+ // time line.
+ if( nFractionElapsedTime < nFractionRequiredCalls )
+ {
+ VERBOSE_TRACE( "SimpleContinuousActivityBase::calcTimeLag(): "
+ "t=%f is based on time", nFractionElapsedTime );
+ return 0.0;
+ }
+ else
+ {
+ VERBOSE_TRACE( "SimpleContinuousActivityBase::perform(): "
+ "t=%f is based on number of calls",
+ nFractionRequiredCalls );
+
+ // lag global time, so all other animations lag, too:
+ return ((nFractionElapsedTime - nFractionRequiredCalls)
+ * mnMinSimpleDuration);
+ }
+ }
+
+ bool SimpleContinuousActivityBase::perform()
+ {
+ // call base class, for start() calls and end handling
+ if( !ActivityBase::perform() )
+ return false; // done, we're ended
+
+
+ // get relative animation position
+ // ===============================
+
+ const double nCurrElapsedTime( maTimer.getElapsedTime() );
+ double nT( nCurrElapsedTime / mnMinSimpleDuration );
+
+
+ // one of the stop criteria reached?
+ // =================================
+
+ // will be set to true below, if one of the termination criteria
+ // matched.
+ bool bActivityEnding( false );
+
+ if( isRepeatCountValid() )
+ {
+ // Finite duration
+ // ===============
+
+ // When we've autoreverse on, the repeat count
+ // doubles
+ const double nRepeatCount( getRepeatCount() );
+ const double nEffectiveRepeat( isAutoReverse() ?
+ 2.0*nRepeatCount :
+ nRepeatCount );
+
+ // time (or frame count) elapsed?
+ if( nEffectiveRepeat <= nT )
+ {
+ // okee. done for now. Will not exit right here,
+ // to give animation the chance to render the last
+ // frame below
+ bActivityEnding = true;
+
+ // clamp animation to max permissible value
+ nT = nEffectiveRepeat;
+ }
+ }
+
+
+ // need to do auto-reverse?
+ // ========================
+
+ double nRepeats;
+ double nRelativeSimpleTime;
+
+ // TODO(Q3): Refactor this mess
+ if( isAutoReverse() )
+ {
+ // divert active duration into repeat and
+ // fractional part.
+ const double nFractionalActiveDuration( modf(nT, &nRepeats) );
+
+ // for auto-reverse, map ranges [1,2), [3,4), ...
+ // to ranges [0,1), [1,2), etc.
+ if( ((int)nRepeats) % 2 )
+ {
+ // we're in an odd range, reverse sweep
+ nRelativeSimpleTime = 1.0 - nFractionalActiveDuration;
+ }
+ else
+ {
+ // we're in an even range, pass on as is
+ nRelativeSimpleTime = nFractionalActiveDuration;
+ }
+
+ // effective repeat count for autoreverse is half of
+ // the input time's value (each run of an autoreverse
+ // cycle is half of a repeat)
+ nRepeats /= 2;
+ }
+ else
+ {
+ // determine repeat
+ // ================
+
+ // calc simple time and number of repeats from nT
+ // Now, that's easy, since the fractional part of
+ // nT gives the relative simple time, and the
+ // integer part the number of full repeats:
+ nRelativeSimpleTime = modf(nT, &nRepeats);
+
+ // clamp repeats to max permissible value (maRepeats.getValue() - 1.0)
+ if( isRepeatCountValid() &&
+ nRepeats >= getRepeatCount() )
+ {
+ // Note that this code here only gets
+ // triggered if maRepeats.getValue() is an
+ // _integer_. Otherwise, nRepeats will never
+ // reach nor exceed
+ // maRepeats.getValue(). Thus, the code below
+ // does not need to handle cases of fractional
+ // repeats, and can always assume that a full
+ // animation run has ended (with
+ // nRelativeSimpleTime=1.0 for
+ // non-autoreversed activities).
+
+ // with modf, nRelativeSimpleTime will never
+ // become 1.0, since nRepeats is incremented and
+ // nRelativeSimpleTime set to 0.0 then.
+ //
+ // For the animation to reach its final value,
+ // nRepeats must although become
+ // maRepeats.getValue()-1.0, and
+ // nRelativeSimpleTime=1.0.
+ nRelativeSimpleTime = 1.0;
+ nRepeats -= 1.0;
+ }
+ }
+
+ // actually perform something
+ // ==========================
+
+ simplePerform( nRelativeSimpleTime,
+ // nRepeats is already integer-valued
+ static_cast<sal_uInt32>( nRepeats ) );
+
+
+ // delayed endActivity() call from end condition check
+ // below. Issued after the simplePerform() call above, to
+ // give animations the chance to correctly reach the
+ // animation end value, without spurious bail-outs because
+ // of isActive() returning false.
+ if( bActivityEnding )
+ endActivity();
+
+ // one more frame successfully performed
+ ++mnCurrPerformCalls;
+
+ return isActive();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activities/simplecontinuousactivitybase.hxx b/slideshow/source/engine/activities/simplecontinuousactivitybase.hxx
new file mode 100644
index 000000000000..73d6b0b6803b
--- /dev/null
+++ b/slideshow/source/engine/activities/simplecontinuousactivitybase.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX
+#define INCLUDED_SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX
+
+#include "activitybase.hxx"
+#include <canvas/elapsedtime.hxx>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Simple, continuous animation.
+
+ This class implements a simple, continuous animation
+ without considering repeats or acceleration on the
+ perform call. Only useful as a base class, you
+ probably want to use ContinuousActivityBase.
+ */
+ class SimpleContinuousActivityBase : public ActivityBase
+ {
+ public:
+ SimpleContinuousActivityBase( const ActivityParameters& rParms );
+
+ virtual double calcTimeLag() const;
+ virtual bool perform();
+
+ protected:
+ /** Hook for derived classes
+
+ This method will be called from perform().
+
+ @param nSimpleTime
+ Simple animation time, without repeat,
+ acceleration or deceleration applied. This value
+ is always in the [0,1] range, the repeat is
+ accounted for with the nRepeatCount parameter.
+
+ @param nRepeatCount
+ Number of full repeats already performed
+ */
+ virtual void simplePerform( double nSimpleTime, sal_uInt32 nRepeatCount ) const = 0;
+
+ virtual void startAnimation();
+
+ private:
+ /// Time elapsed since activity started
+ ::canvas::tools::ElapsedTime maTimer;
+
+ /// Simple duration of activity
+ const double mnMinSimpleDuration;
+
+ /// Minimal number of frames to show (see ActivityParameters)
+ const sal_uInt32 mnMinNumberOfFrames;
+
+ /// Actual number of frames shown until now.
+ sal_uInt32 mnCurrPerformCalls;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SIMPLECONTINUOUSACTIVITYBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/activitiesqueue.cxx b/slideshow/source/engine/activitiesqueue.cxx
new file mode 100644
index 000000000000..76174958b2a1
--- /dev/null
+++ b/slideshow/source/engine/activitiesqueue.cxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include "slideshowexceptions.hxx"
+#include "activity.hxx"
+#include "activitiesqueue.hxx"
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ActivitiesQueue::ActivitiesQueue(
+ const ::boost::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer ) :
+ mpTimer( pPresTimer ),
+ maCurrentActivitiesWaiting(),
+ maCurrentActivitiesReinsert(),
+ maDequeuedActivities()
+ {
+ }
+
+ ActivitiesQueue::~ActivitiesQueue()
+ {
+ // dispose all queue entries
+ try
+ {
+ std::for_each( maCurrentActivitiesWaiting.begin(),
+ maCurrentActivitiesWaiting.end(),
+ boost::mem_fn( &Disposable::dispose ) );
+ std::for_each( maCurrentActivitiesReinsert.begin(),
+ maCurrentActivitiesReinsert.end(),
+ boost::mem_fn( &Disposable::dispose ) );
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity )
+ {
+ OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" );
+
+ if( !pActivity )
+ return false;
+
+ // add entry to waiting list
+ maCurrentActivitiesWaiting.push_back( pActivity );
+
+ return true;
+ }
+
+ void ActivitiesQueue::process()
+ {
+ VERBOSE_TRACE( "ActivitiesQueue: outer loop heartbeat" );
+
+ // accumulate time lag for all activities, and lag time
+ // base if necessary:
+ ActivityQueue::const_iterator iPos(
+ maCurrentActivitiesWaiting.begin() );
+ const ActivityQueue::const_iterator iEnd(
+ maCurrentActivitiesWaiting.end() );
+ double fLag = 0.0;
+ for ( ; iPos != iEnd; ++iPos )
+ fLag = std::max<double>( fLag, (*iPos)->calcTimeLag() );
+ if (fLag > 0.0)
+ {
+ mpTimer->adjustTimer( -fLag );
+ }
+
+ // process list of activities
+ while( !maCurrentActivitiesWaiting.empty() )
+ {
+ // process topmost activity
+ ActivitySharedPtr pActivity( maCurrentActivitiesWaiting.front() );
+ maCurrentActivitiesWaiting.pop_front();
+
+ bool bReinsert( false );
+
+ try
+ {
+ // fire up activity
+ bReinsert = pActivity->perform();
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ // catch anything here, we don't want
+ // to leave this scope under _any_
+ // circumstance. Although, do _not_
+ // reinsert an activity that threw
+ // once.
+
+ // NOTE: we explicitely don't catch(...) here,
+ // since this will also capture segmentation
+ // violations and the like. In such a case, we
+ // still better let our clients now...
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ catch( SlideShowException& )
+ {
+ // catch anything here, we don't want
+ // to leave this scope under _any_
+ // circumstance. Although, do _not_
+ // reinsert an activity that threw
+ // once.
+
+ // NOTE: we explicitely don't catch(...) here,
+ // since this will also capture segmentation
+ // violations and the like. In such a case, we
+ // still better let our clients now...
+ OSL_TRACE( "::presentation::internal::ActivitiesQueue: Activity threw a SlideShowException, removing from ring" );
+ }
+
+ if( bReinsert )
+ maCurrentActivitiesReinsert.push_back( pActivity );
+ else
+ maDequeuedActivities.push_back( pActivity );
+
+ VERBOSE_TRACE( "ActivitiesQueue: inner loop heartbeat" );
+ }
+
+ if( !maCurrentActivitiesReinsert.empty() )
+ {
+ // reinsert all processed, but not finished
+ // activities back to waiting queue. With swap(),
+ // we kill two birds with one stone: we reuse the
+ // list nodes, and we clear the
+ // maCurrentActivitiesReinsert list
+ maCurrentActivitiesWaiting.swap( maCurrentActivitiesReinsert );
+ }
+ }
+
+ void ActivitiesQueue::processDequeued()
+ {
+ // notify all dequeued activities from last round
+ ::std::for_each( maDequeuedActivities.begin(),
+ maDequeuedActivities.end(),
+ ::boost::mem_fn( &Activity::dequeued ) );
+ maDequeuedActivities.clear();
+ }
+
+ bool ActivitiesQueue::isEmpty() const
+ {
+ return maCurrentActivitiesWaiting.empty() && maCurrentActivitiesReinsert.empty();
+ }
+
+ void ActivitiesQueue::clear()
+ {
+ // dequeue all entries:
+ std::for_each( maCurrentActivitiesWaiting.begin(),
+ maCurrentActivitiesWaiting.end(),
+ boost::mem_fn( &Activity::dequeued ) );
+ ActivityQueue().swap( maCurrentActivitiesWaiting );
+
+ std::for_each( maCurrentActivitiesReinsert.begin(),
+ maCurrentActivitiesReinsert.end(),
+ boost::mem_fn( &Activity::dequeued ) );
+ ActivityQueue().swap( maCurrentActivitiesReinsert );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animatedsprite.cxx b/slideshow/source/engine/animatedsprite.cxx
new file mode 100644
index 000000000000..d4188b6a7f62
--- /dev/null
+++ b/slideshow/source/engine/animatedsprite.cxx
@@ -0,0 +1,228 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <animatedsprite.hxx>
+
+#include <cppcanvas/canvas.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ AnimatedSprite::AnimatedSprite( const ViewLayerSharedPtr& rViewLayer,
+ const ::basegfx::B2DSize& rSpriteSizePixel,
+ double nSpritePrio ) :
+ mpViewLayer( rViewLayer ),
+ mpSprite(),
+ maEffectiveSpriteSizePixel( rSpriteSizePixel ),
+ maContentPixelOffset(),
+ mnSpritePrio(nSpritePrio),
+ mnAlpha(0.0),
+ maPosPixel(),
+ maClip(),
+ maTransform(),
+ mbSpriteVisible( false )
+ {
+ ENSURE_OR_THROW( mpViewLayer, "AnimatedSprite::AnimatedSprite(): Invalid view layer" );
+
+ // Add half a pixel tolerance to sprite size, since we later on compare
+ // against it in resize(). And view transformations will almost never yield
+ // the same data bits when transforming to device coordinates
+ maEffectiveSpriteSizePixel += ::basegfx::B2DSize(0.5, 0.5);
+
+ mpSprite = mpViewLayer->createSprite( maEffectiveSpriteSizePixel,
+ mnSpritePrio );
+
+ ENSURE_OR_THROW( mpSprite, "AnimatedSprite::AnimatedSprite(): Could not create sprite" );
+ }
+
+ ::cppcanvas::CanvasSharedPtr AnimatedSprite::getContentCanvas() const
+ {
+ ENSURE_OR_THROW( mpViewLayer->getCanvas(), "AnimatedSprite::getContentCanvas(): No view layer canvas" );
+
+ const ::cppcanvas::CanvasSharedPtr pContentCanvas( mpSprite->getContentCanvas() );
+ pContentCanvas->clear();
+
+ // extract linear part of canvas view transformation
+ // (linear means: without translational components). The
+ // only translation that is imposed at the view transform
+ // is the local content pixel offset.
+ //
+ // We can apply that directly here, no need to call
+ // aLinearTransform.translate(), since, as said above, the
+ // last column of aLinearTransform is assumed [0 0 1]
+ ::basegfx::B2DHomMatrix aLinearTransform( mpViewLayer->getTransformation() );
+ aLinearTransform.set( 0, 2, maContentPixelOffset.getX() );
+ aLinearTransform.set( 1, 2, maContentPixelOffset.getY() );
+
+ // apply linear part of canvas view transformation to sprite canvas
+ pContentCanvas->setTransformation( aLinearTransform );
+
+ return pContentCanvas;
+ }
+
+ bool AnimatedSprite::resize( const ::basegfx::B2DSize& rSpriteSizePixel )
+ {
+ // Enlarge or reduce the sprite size, if necessary. This
+ // method employs a strategy similar to container, when
+ // allocating memory: size is doubled or halved everytime
+ // the limit is reached. This makes for amortized constant
+ // time in runtime complexity. Note that we take exact
+ // powers of two here, since several HW-accelerated canvas
+ // implementations are limited to such sprite sizes
+ // (otherwise, those implementations would internally
+ // round up, too, wasting precious mem).
+ ::basegfx::B2DSize aNewSize( maEffectiveSpriteSizePixel );
+ bool bNeedResize( false );
+
+ if( rSpriteSizePixel.getX() > maEffectiveSpriteSizePixel.getX() ||
+ rSpriteSizePixel.getX() < 0.5*maEffectiveSpriteSizePixel.getX() )
+ {
+ // enlarge or shrink width
+ aNewSize.setX( ::canvas::tools::nextPow2( ::basegfx::fround(rSpriteSizePixel.getX()) ) );
+ bNeedResize = true;
+ }
+
+ if( rSpriteSizePixel.getY() > maEffectiveSpriteSizePixel.getY() ||
+ rSpriteSizePixel.getY() < 0.5*maEffectiveSpriteSizePixel.getY() )
+ {
+ // enlarge or shrink height, by doubling it
+ aNewSize.setY( ::canvas::tools::nextPow2( ::basegfx::fround(rSpriteSizePixel.getY()) ) );
+ bNeedResize = true;
+ }
+
+ if( bNeedResize )
+ {
+ // as the old sprite might have already been altered
+ // (and therefore been placed in the update list of
+ // the spritecanvas for this frame), must hide it
+ // here, to ensure it's not visible on screen any
+ // longer.
+ mpSprite->hide();
+
+ maEffectiveSpriteSizePixel = aNewSize;
+ mpSprite = mpViewLayer->createSprite( maEffectiveSpriteSizePixel,
+ mnSpritePrio );
+
+ ENSURE_OR_THROW( mpSprite,
+ "AnimatedSprite::resize(): Could not create new sprite" );
+
+ // set attributes similar to previous sprite
+ if( mpSprite && mbSpriteVisible )
+ {
+ mpSprite->show();
+ mpSprite->setAlpha( mnAlpha );
+
+ if( maPosPixel )
+ mpSprite->movePixel( *maPosPixel );
+
+ if( maClip )
+ mpSprite->setClip( *maClip );
+ }
+ }
+
+ return mpSprite;
+ }
+
+ void AnimatedSprite::setPixelOffset( const ::basegfx::B2DSize& rPixelOffset )
+ {
+ maContentPixelOffset = rPixelOffset;
+ }
+
+ ::basegfx::B2DSize AnimatedSprite::getPixelOffset() const
+ {
+ return maContentPixelOffset;
+ }
+
+ void AnimatedSprite::movePixel( const ::basegfx::B2DPoint& rNewPos )
+ {
+ maPosPixel.reset( rNewPos );
+ mpSprite->movePixel( rNewPos );
+ }
+
+ void AnimatedSprite::setAlpha( double nAlpha )
+ {
+ mnAlpha = nAlpha;
+ mpSprite->setAlpha( nAlpha );
+ }
+
+ void AnimatedSprite::clip( const ::basegfx::B2DPolyPolygon& rClip )
+ {
+ maClip.reset( rClip );
+ mpSprite->setClipPixel( rClip );
+ }
+
+ void AnimatedSprite::clip()
+ {
+ maClip.reset();
+ mpSprite->setClip();
+ }
+
+ void AnimatedSprite::transform( const ::basegfx::B2DHomMatrix& rTransform )
+ {
+ maTransform.reset( rTransform );
+ mpSprite->transform( rTransform );
+ }
+
+ void AnimatedSprite::setPriority( double nPrio )
+ {
+ mpSprite->setPriority( nPrio );
+ }
+
+ void AnimatedSprite::hide()
+ {
+ mpSprite->hide();
+ mbSpriteVisible = false;
+ }
+
+ void AnimatedSprite::show()
+ {
+ mbSpriteVisible = true;
+ mpSprite->show();
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationfactory.cxx b/slideshow/source/engine/animationfactory.cxx
new file mode 100644
index 000000000000..f5407ad9831c
--- /dev/null
+++ b/slideshow/source/engine/animationfactory.cxx
@@ -0,0 +1,1389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <animationfactory.hxx>
+#include <attributemap.hxx>
+
+#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
+#include <com/sun/star/animations/AnimationTransformType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+#include <functional>
+
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ namespace
+ {
+ // attention, there is a similar implementation of Animation in
+ // transitions/transitionfactory.cxx
+
+ template< typename ValueT > class TupleAnimation : public PairAnimation
+ {
+ public:
+ TupleAnimation( const ShapeManagerSharedPtr& rShapeManager,
+ int nFlags,
+ bool (ShapeAttributeLayer::*pIs1stValid)() const,
+ bool (ShapeAttributeLayer::*pIs2ndValid)() const,
+ const ValueT& rDefaultValue,
+ const ::basegfx::B2DSize& rReferenceSize,
+ double (ShapeAttributeLayer::*pGet1stValue)() const,
+ double (ShapeAttributeLayer::*pGet2ndValue)() const,
+ void (ShapeAttributeLayer::*pSetValue)( const ValueT& ) ) :
+ mpShape(),
+ mpAttrLayer(),
+ mpShapeManager( rShapeManager ),
+ mpIs1stValidFunc(pIs1stValid),
+ mpIs2ndValidFunc(pIs2ndValid),
+ mpGet1stValueFunc(pGet1stValue),
+ mpGet2ndValueFunc(pGet2ndValue),
+ mpSetValueFunc(pSetValue),
+ mnFlags( nFlags ),
+ maReferenceSize( rReferenceSize ),
+ maDefaultValue( rDefaultValue ),
+ mbAnimationStarted( false )
+ {
+ ENSURE_OR_THROW( rShapeManager,
+ "TupleAnimation::TupleAnimation(): Invalid ShapeManager" );
+ ENSURE_OR_THROW( pIs1stValid && pIs2ndValid && pGet1stValue && pGet2ndValue && pSetValue,
+ "TupleAnimation::TupleAnimation(): One of the method pointers is NULL" );
+ }
+
+ ~TupleAnimation()
+ {
+ end_();
+ }
+
+ // Animation interface
+ // -------------------
+ virtual void prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& )
+ {}
+
+ virtual void start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+ {
+ OSL_ENSURE( !mpShape,
+ "TupleAnimation::start(): Shape already set" );
+ OSL_ENSURE( !mpAttrLayer,
+ "TupleAnimation::start(): Attribute layer already set" );
+
+ mpShape = rShape;
+ mpAttrLayer = rAttrLayer;
+
+ ENSURE_OR_THROW( rShape,
+ "TupleAnimation::start(): Invalid shape" );
+ ENSURE_OR_THROW( rAttrLayer,
+ "TupleAnimation::start(): Invalid attribute layer" );
+
+ if( !mbAnimationStarted )
+ {
+ mbAnimationStarted = true;
+
+ if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
+ mpShapeManager->enterAnimationMode( mpShape );
+ }
+ }
+
+ virtual void end() { end_(); }
+ void end_()
+ {
+ if( mbAnimationStarted )
+ {
+ mbAnimationStarted = false;
+
+ if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
+ mpShapeManager->leaveAnimationMode( mpShape );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+ }
+ }
+
+ // PairAnimation interface
+ // -----------------------
+
+ virtual bool operator()( const ::basegfx::B2DTuple& rValue )
+ {
+ ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
+ "TupleAnimation::operator(): Invalid ShapeAttributeLayer" );
+
+ ValueT aValue( rValue.getX(),
+ rValue.getY() );
+
+ // Activitis get values from the expression parser,
+ // which returns _relative_ sizes/positions.
+ // Convert back relative to reference coordinate system
+ aValue *= maReferenceSize;
+
+ ((*mpAttrLayer).*mpSetValueFunc)( aValue );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+
+ return true;
+ }
+
+ virtual ::basegfx::B2DTuple getUnderlyingValue() const
+ {
+ ENSURE_OR_THROW( mpAttrLayer,
+ "TupleAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
+
+ ::basegfx::B2DTuple aRetVal;
+
+ // deviated from the (*shared_ptr).*mpFuncPtr
+ // notation here, since gcc does not seem to parse
+ // that as a member function call anymore.
+ aRetVal.setX( (mpAttrLayer.get()->*mpIs1stValidFunc)() ?
+ (mpAttrLayer.get()->*mpGet1stValueFunc)() :
+ maDefaultValue.getX() );
+ aRetVal.setY( (mpAttrLayer.get()->*mpIs2ndValidFunc)() ?
+ (mpAttrLayer.get()->*mpGet2ndValueFunc)() :
+ maDefaultValue.getY() );
+
+ // Activities get values from the expression
+ // parser, which returns _relative_
+ // sizes/positions. Convert start value to the
+ // same coordinate space (i.e. relative to given
+ // reference size).
+ aRetVal /= maReferenceSize;
+
+ return aRetVal;
+ }
+
+ private:
+ AnimatableShapeSharedPtr mpShape;
+ ShapeAttributeLayerSharedPtr mpAttrLayer;
+ ShapeManagerSharedPtr mpShapeManager;
+ bool (ShapeAttributeLayer::*mpIs1stValidFunc)() const;
+ bool (ShapeAttributeLayer::*mpIs2ndValidFunc)() const;
+ double (ShapeAttributeLayer::*mpGet1stValueFunc)() const;
+ double (ShapeAttributeLayer::*mpGet2ndValueFunc)() const;
+ void (ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
+
+ const int mnFlags;
+
+ const ::basegfx::B2DSize maReferenceSize;
+ const ValueT maDefaultValue;
+ bool mbAnimationStarted;
+ };
+
+
+ class PathAnimation : public NumberAnimation
+ {
+ public:
+ PathAnimation( const ::rtl::OUString& rSVGDPath,
+ sal_Int16 nAdditive,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags ) :
+ maPathPoly(),
+ mpShape(),
+ mpAttrLayer(),
+ mpShapeManager( rShapeManager ),
+ maPageSize( rSlideSize ),
+ maShapeOrig(),
+ mnFlags( nFlags ),
+ mbAnimationStarted( false ),
+ mnAdditive( nAdditive )
+ {
+ ENSURE_OR_THROW( rShapeManager,
+ "PathAnimation::PathAnimation(): Invalid ShapeManager" );
+
+ ::basegfx::B2DPolyPolygon aPolyPoly;
+
+ ENSURE_OR_THROW( ::basegfx::tools::importFromSvgD( aPolyPoly, rSVGDPath ),
+ "PathAnimation::PathAnimation(): failed to parse SVG:d path" );
+ ENSURE_OR_THROW( aPolyPoly.count() == 1,
+ "PathAnimation::PathAnimation(): motion path consists of multiple/zero polygon(s)" );
+
+ // TODO(F2): Since getPositionRelative() currently
+ // cannot handle beziers, have to subdivide.
+ // AW: Should be no longer necessary; getPositionRelative is now bezier-safe
+ maPathPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aPolyPoly.getB2DPolygon(0) );
+ }
+
+ ~PathAnimation()
+ {
+ end_();
+ }
+
+ // Animation interface
+ // -------------------
+ virtual void prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& )
+ {}
+
+ virtual void start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+ {
+ OSL_ENSURE( !mpShape,
+ "PathAnimation::start(): Shape already set" );
+ OSL_ENSURE( !mpAttrLayer,
+ "PathAnimation::start(): Attribute layer already set" );
+
+ mpShape = rShape;
+ mpAttrLayer = rAttrLayer;
+
+ ENSURE_OR_THROW( rShape,
+ "PathAnimation::start(): Invalid shape" );
+ ENSURE_OR_THROW( rAttrLayer,
+ "PathAnimation::start(): Invalid attribute layer" );
+
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ if( mnAdditive == animations::AnimationAdditiveMode::SUM )
+ maShapeOrig = mpShape->getBounds().getCenter();
+ else
+ maShapeOrig = mpShape->getDomBounds().getCenter();
+
+ if( !mbAnimationStarted )
+ {
+ mbAnimationStarted = true;
+
+ if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
+ mpShapeManager->enterAnimationMode( mpShape );
+ }
+ }
+
+ virtual void end() { end_(); }
+ void end_()
+ {
+ if( mbAnimationStarted )
+ {
+ mbAnimationStarted = false;
+
+ if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
+ mpShapeManager->leaveAnimationMode( mpShape );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+ }
+ }
+
+ // NumberAnimation interface
+ // -----------------------
+
+ virtual bool operator()( double nValue )
+ {
+ ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
+ "PathAnimation::operator(): Invalid ShapeAttributeLayer" );
+
+ ::basegfx::B2DPoint rOutPos = ::basegfx::tools::getPositionRelative( maPathPoly,
+ nValue );
+
+ // TODO(F1): Determine whether the path is
+ // absolute, or shape-relative.
+
+ // interpret path as page-relative. Scale up with page size
+ rOutPos *= maPageSize;
+
+ // TODO(F1): Determine whether the path origin is
+ // absolute, or shape-relative.
+
+ // interpret path as shape-originated. Offset to shape position
+
+ rOutPos += maShapeOrig;
+
+ mpAttrLayer->setPosition( rOutPos );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+
+ return true;
+ }
+
+ virtual double getUnderlyingValue() const
+ {
+ ENSURE_OR_THROW( mpAttrLayer,
+ "PathAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
+
+ return 0.0; // though this should be used in concert with
+ // ActivitiesFactory::createSimpleActivity, better
+ // explicitely name our start value.
+ // Permissible range for operator() above is [0,1]
+ }
+
+ private:
+ ::basegfx::B2DPolygon maPathPoly;
+ AnimatableShapeSharedPtr mpShape;
+ ShapeAttributeLayerSharedPtr mpAttrLayer;
+ ShapeManagerSharedPtr mpShapeManager;
+ const ::basegfx::B2DSize maPageSize;
+ ::basegfx::B2DPoint maShapeOrig;
+ const int mnFlags;
+ bool mbAnimationStarted;
+ sal_Int16 mnAdditive;
+ };
+
+
+ /** GenericAnimation template
+
+ This template makes heavy use of SFINAE, only one of
+ the operator()() methods will compile for each of the
+ base classes.
+
+ Note that we omit the virtual keyword on the
+ operator()() overrides and getUnderlyingValue() methods on
+ purpose; those that actually do override baseclass
+ virtual methods inherit the property, and the others
+ won't increase our vtable. What's more, having all
+ those methods in the vtable actually creates POIs for
+ them, which breaks the whole SFINAE concept (IOW, this
+ template won't compile any longer).
+
+ @tpl AnimationBase
+ Type of animation to generate (determines the
+ interface GenericAnimation will implement). Must be
+ one of NumberAnimation, ColorAnimation,
+ StringAnimation, PairAnimation or BoolAnimation.
+
+ @tpl ModifierFunctor
+ Type of a functor object, which can optionally be used to
+ modify the getter/setter values.
+ */
+ template< typename AnimationBase, typename ModifierFunctor > class GenericAnimation : public AnimationBase
+ {
+ public:
+ typedef typename AnimationBase::ValueType ValueT;
+
+ /** Create generic animation
+
+ @param pIsValid
+ Function pointer to one of the is*Valid
+ methods. Used to either take the given getter
+ method, or the given default value for the start value.
+
+ @param rDefaultValue
+ Default value, to take as the start value if
+ is*Valid returns false.
+
+ @param pGetValue
+ Getter method, to fetch start value if valid.
+
+ @param pSetValue
+ Setter method. This one puts the current animation
+ value to the ShapeAttributeLayer.
+
+ @param rGetterModifier
+ Modifies up values retrieved from the pGetValue method.
+ Must provide operator()( const ValueT& ) method.
+
+ @param rSetterModifier
+ Modifies up values before passing them to the pSetValue method.
+ Must provide operator()( const ValueT& ) method.
+ */
+ GenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
+ int nFlags,
+ bool (ShapeAttributeLayer::*pIsValid)() const,
+ const ValueT& rDefaultValue,
+ ValueT (ShapeAttributeLayer::*pGetValue)() const,
+ void (ShapeAttributeLayer::*pSetValue)( const ValueT& ),
+ const ModifierFunctor& rGetterModifier,
+ const ModifierFunctor& rSetterModifier ) :
+ mpShape(),
+ mpAttrLayer(),
+ mpShapeManager( rShapeManager ),
+ mpIsValidFunc(pIsValid),
+ mpGetValueFunc(pGetValue),
+ mpSetValueFunc(pSetValue),
+ maGetterModifier( rGetterModifier ),
+ maSetterModifier( rSetterModifier ),
+ mnFlags( nFlags ),
+ maDefaultValue(rDefaultValue),
+ mbAnimationStarted( false )
+ {
+ ENSURE_OR_THROW( rShapeManager,
+ "GenericAnimation::GenericAnimation(): Invalid ShapeManager" );
+ ENSURE_OR_THROW( pIsValid && pGetValue && pSetValue,
+ "GenericAnimation::GenericAnimation(): One of the method pointers is NULL" );
+ }
+
+ ~GenericAnimation()
+ {
+ end_();
+ }
+
+ // Animation interface
+ // -------------------
+ virtual void prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& )
+ {}
+
+ virtual void start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+ {
+ OSL_ENSURE( !mpShape,
+ "GenericAnimation::start(): Shape already set" );
+ OSL_ENSURE( !mpAttrLayer,
+ "GenericAnimation::start(): Attribute layer already set" );
+
+ mpShape = rShape;
+ mpAttrLayer = rAttrLayer;
+
+ ENSURE_OR_THROW( rShape,
+ "GenericAnimation::start(): Invalid shape" );
+ ENSURE_OR_THROW( rAttrLayer,
+ "GenericAnimation::start(): Invalid attribute layer" );
+
+ // only start animation once per repeated start() call,
+ // and only if sprites should be used for display
+ if( !mbAnimationStarted )
+ {
+ mbAnimationStarted = true;
+
+ if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
+ mpShapeManager->enterAnimationMode( mpShape );
+ }
+ }
+
+ virtual void end() { end_(); }
+ void end_()
+ {
+ // TODO(Q2): Factor out common code (most
+ // prominently start() and end()) into base class
+
+ // only stop animation once per repeated end() call,
+ // and only if sprites are used for display
+ if( mbAnimationStarted )
+ {
+ mbAnimationStarted = false;
+
+ if( !(mnFlags & AnimationFactory::FLAG_NO_SPRITE) )
+ mpShapeManager->leaveAnimationMode( mpShape );
+
+ // Attention, this notifyShapeUpdate() is
+ // somewhat delicate here. Calling it
+ // unconditional (i.e. not guarded by
+ // mbAnimationStarted) will lead to shapes
+ // snapping back to their original state just
+ // before the slide ends. Not calling it at
+ // all might swallow final animation
+ // states. The current implementation relies
+ // on the fact that end() is either called by
+ // the Activity (then, the last animation
+ // state has been set, and corresponds to the
+ // shape's hold state), or by the animation
+ // node (then, it's a forced end, and we
+ // _have_ to snap back).
+ //
+ // To reiterate: normally, we're called from
+ // the Activity first, thus the
+ // notifyShapeUpdate() below will update to
+ // the last activity value.
+
+ // force shape update, activity might have changed
+ // state in the last round.
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+ }
+ }
+
+ // Derived Animation interface
+ // ---------------------------
+
+ /** For by-reference interfaces (B2DTuple, OUString)
+ */
+ bool operator()( const ValueT& x )
+ {
+ ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
+ "GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
+
+ ((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+
+ return true;
+ }
+
+ /** For by-value interfaces (bool, double)
+ */
+ bool operator()( ValueT x )
+ {
+ ENSURE_OR_RETURN_FALSE( mpAttrLayer && mpShape,
+ "GenericAnimation::operator(): Invalid ShapeAttributeLayer" );
+
+ ((*mpAttrLayer).*mpSetValueFunc)( maSetterModifier( x ) );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+
+ return true;
+ }
+
+ ValueT getUnderlyingValue() const
+ {
+ ENSURE_OR_THROW( mpAttrLayer,
+ "GenericAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
+
+ // deviated from the (*shared_ptr).*mpFuncPtr
+ // notation here, since gcc does not seem to parse
+ // that as a member function call anymore.
+ if( (mpAttrLayer.get()->*mpIsValidFunc)() )
+ return maGetterModifier( ((*mpAttrLayer).*mpGetValueFunc)() );
+ else
+ return maDefaultValue;
+ }
+
+ private:
+ AnimatableShapeSharedPtr mpShape;
+ ShapeAttributeLayerSharedPtr mpAttrLayer;
+ ShapeManagerSharedPtr mpShapeManager;
+ bool (ShapeAttributeLayer::*mpIsValidFunc)() const;
+ ValueT (ShapeAttributeLayer::*mpGetValueFunc)() const;
+ void (ShapeAttributeLayer::*mpSetValueFunc)( const ValueT& );
+
+ ModifierFunctor maGetterModifier;
+ ModifierFunctor maSetterModifier;
+
+ const int mnFlags;
+
+ const ValueT maDefaultValue;
+ bool mbAnimationStarted;
+ };
+
+ /** Function template wrapper around GenericAnimation template
+
+ @tpl AnimationBase
+ Type of animation to generate (determines the
+ interface GenericAnimation will implement).
+ */
+ template< typename AnimationBase > ::boost::shared_ptr< AnimationBase >
+ makeGenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
+ int nFlags,
+ bool (ShapeAttributeLayer::*pIsValid)() const,
+ const typename AnimationBase::ValueType& rDefaultValue,
+ typename AnimationBase::ValueType (ShapeAttributeLayer::*pGetValue)() const,
+ void (ShapeAttributeLayer::*pSetValue)( const typename AnimationBase::ValueType& ) )
+ {
+ return ::boost::shared_ptr< AnimationBase >(
+ new GenericAnimation< AnimationBase,
+ ::std::identity< typename AnimationBase::ValueType > >(
+ rShapeManager,
+ nFlags,
+ pIsValid,
+ rDefaultValue,
+ pGetValue,
+ pSetValue,
+ // no modification necessary, use identity functor here
+ ::std::identity< typename AnimationBase::ValueType >(),
+ ::std::identity< typename AnimationBase::ValueType >() ) );
+ }
+
+ class Scaler
+ {
+ public:
+ Scaler( double nScale ) :
+ mnScale( nScale )
+ {
+ }
+
+ double operator()( double nVal ) const
+ {
+ return mnScale * nVal;
+ }
+
+ private:
+ double mnScale;
+ };
+
+ /** Overload for NumberAnimations which need scaling (width,height,x,y currently)
+ */
+ NumberAnimationSharedPtr makeGenericAnimation( const ShapeManagerSharedPtr& rShapeManager,
+ int nFlags,
+ bool (ShapeAttributeLayer::*pIsValid)() const,
+ double nDefaultValue,
+ double (ShapeAttributeLayer::*pGetValue)() const,
+ void (ShapeAttributeLayer::*pSetValue)( const double& ),
+ double nScaleValue )
+ {
+ return NumberAnimationSharedPtr(
+ new GenericAnimation< NumberAnimation, Scaler >( rShapeManager,
+ nFlags,
+ pIsValid,
+ nDefaultValue / nScaleValue,
+ pGetValue,
+ pSetValue,
+ Scaler( 1.0/nScaleValue ),
+ Scaler( nScaleValue ) ) );
+ }
+
+
+ uno::Any getShapeDefault( const AnimatableShapeSharedPtr& rShape,
+ const ::rtl::OUString& rPropertyName )
+ {
+ uno::Reference< drawing::XShape > xShape( rShape->getXShape() );
+
+ if( !xShape.is() )
+ return uno::Any(); // no regular shape, no defaults available
+
+
+ // extract relevant value from XShape's PropertySet
+ uno::Reference< beans::XPropertySet > xPropSet( xShape,
+ uno::UNO_QUERY );
+
+ ENSURE_OR_THROW( xPropSet.is(),
+ "getShapeDefault(): Cannot query property set from shape" );
+
+ return xPropSet->getPropertyValue( rPropertyName );
+ }
+
+ template< typename ValueType > ValueType getDefault( const AnimatableShapeSharedPtr& rShape,
+ const ::rtl::OUString& rPropertyName )
+ {
+ const uno::Any& rAny( getShapeDefault( rShape,
+ rPropertyName ) );
+
+ if( !rAny.hasValue() )
+ {
+ OSL_ENSURE( false, "getDefault(): cannot get requested shape property" );
+ OSL_TRACE( "getDefault(): cannot get '%s' shape property",
+ ::rtl::OUStringToOString( rPropertyName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+ return ValueType();
+ }
+ else
+ {
+ ValueType aValue = ValueType();
+
+ if( !(rAny >>= aValue) )
+ {
+ OSL_ENSURE( false, "getDefault(): cannot extract requested shape property" );
+ OSL_TRACE( "getDefault(): cannot extract '%s' shape property",
+ ::rtl::OUStringToOString( rPropertyName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+ return ValueType();
+ }
+
+ return aValue;
+ }
+ }
+
+ template<> RGBColor getDefault< RGBColor >( const AnimatableShapeSharedPtr& rShape,
+ const ::rtl::OUString& rPropertyName )
+ {
+ const uno::Any& rAny( getShapeDefault( rShape,
+ rPropertyName ) );
+
+ if( !rAny.hasValue() )
+ {
+ OSL_ENSURE( false, "getDefault(): cannot get requested shape color property" );
+ OSL_TRACE( "getDefault(): cannot get '%s' shape color property",
+ ::rtl::OUStringToOString( rPropertyName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+ return RGBColor();
+ }
+ else
+ {
+ sal_Int32 nValue = 0;
+
+ if( !(rAny >>= nValue) )
+ {
+ OSL_ENSURE( false, "getDefault(): cannot extract requested shape color property" );
+ OSL_TRACE( "getDefault(): cannot extract '%s' shape color property",
+ ::rtl::OUStringToOString( rPropertyName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+ return RGBColor();
+ }
+
+ // convert from 0xAARRGGBB API color to 0xRRGGBB00
+ // canvas color
+ return RGBColor( (nValue << 8U) & 0xFFFFFF00U );
+ }
+ }
+ }
+
+ AnimationFactory::AttributeClass AnimationFactory::classifyAttributeName( const ::rtl::OUString& rAttrName )
+ {
+ // ATTENTION: When changing this map, also the create*PropertyAnimation() methods must
+ // be checked and possibly adapted in their switch statements
+
+ // TODO(Q2): Since this map must be coherent with the various switch statements
+ // in the create*PropertyAnimation methods, try to unify into a single method or table
+ switch( mapAttributeName( rAttrName ) )
+ {
+ default:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_INVALID:
+ return CLASS_UNKNOWN_PROPERTY;
+
+ case ATTRIBUTE_CHAR_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_DIMCOLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_COLOR:
+ return CLASS_COLOR_PROPERTY;
+
+ case ATTRIBUTE_CHAR_FONT_NAME:
+ return CLASS_STRING_PROPERTY;
+
+ case ATTRIBUTE_VISIBILITY:
+ return CLASS_BOOL_PROPERTY;
+
+ case ATTRIBUTE_CHAR_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_WEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_ROTATION:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_OPACITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_ROTATE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_WIDTH:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_Y:
+ return CLASS_NUMBER_PROPERTY;
+
+ case ATTRIBUTE_CHAR_UNDERLINE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_POSTURE:
+ return CLASS_ENUM_PROPERTY;
+ }
+ }
+
+ NumberAnimationSharedPtr AnimationFactory::createNumberPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags )
+ {
+ // ATTENTION: When changing this map, also the classifyAttributeName() method must
+ // be checked and possibly adapted in their switch statement
+ switch( mapAttributeName( rAttrName ) )
+ {
+ default:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_INVALID:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createNumberPropertyAnimation(): Unknown attribute" );
+ break;
+
+ case ATTRIBUTE_CHAR_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_FONT_NAME:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_POSTURE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_UNDERLINE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_DIMCOLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_VISIBILITY:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createNumberPropertyAnimation(): Attribute type mismatch" );
+ break;
+
+ case ATTRIBUTE_CHAR_HEIGHT:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isCharScaleValid,
+ 1.0, // CharHeight is a relative attribute, thus
+ // default is 1.0
+ &ShapeAttributeLayer::getCharScale,
+ &ShapeAttributeLayer::setCharScale );
+
+ case ATTRIBUTE_CHAR_WEIGHT:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isCharWeightValid,
+ getDefault<double>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getCharWeight,
+ &ShapeAttributeLayer::setCharWeight );
+
+ case ATTRIBUTE_CHAR_ROTATION:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isCharRotationAngleValid,
+ getDefault<double>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getCharRotationAngle,
+ &ShapeAttributeLayer::setCharRotationAngle );
+
+ case ATTRIBUTE_HEIGHT:
+ return makeGenericAnimation( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isHeightValid,
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ rShape->getBounds().getHeight(),
+ &ShapeAttributeLayer::getHeight,
+ &ShapeAttributeLayer::setHeight,
+ // convert expression parser value from relative page size
+ rSlideSize.getY() );
+
+ case ATTRIBUTE_OPACITY:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isAlphaValid,
+ // TODO(F1): Provide shape default here (FillTransparency?)
+ 1.0,
+ &ShapeAttributeLayer::getAlpha,
+ &ShapeAttributeLayer::setAlpha );
+
+ case ATTRIBUTE_ROTATE:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isRotationAngleValid,
+ // NOTE: Since we paint the shape as-is from metafile,
+ // rotation angle is always 0.0, even for rotated shapes
+ 0.0,
+ &ShapeAttributeLayer::getRotationAngle,
+ &ShapeAttributeLayer::setRotationAngle );
+
+ case ATTRIBUTE_SKEW_X:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isShearXAngleValid,
+ // TODO(F1): Is there any shape property for skew?
+ 0.0,
+ &ShapeAttributeLayer::getShearXAngle,
+ &ShapeAttributeLayer::setShearXAngle );
+
+ case ATTRIBUTE_SKEW_Y:
+ return makeGenericAnimation<NumberAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isShearYAngleValid,
+ // TODO(F1): Is there any shape property for skew?
+ 0.0,
+ &ShapeAttributeLayer::getShearYAngle,
+ &ShapeAttributeLayer::setShearYAngle );
+
+ case ATTRIBUTE_WIDTH:
+ return makeGenericAnimation( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isWidthValid,
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ rShape->getBounds().getWidth(),
+ &ShapeAttributeLayer::getWidth,
+ &ShapeAttributeLayer::setWidth,
+ // convert expression parser value from relative page size
+ rSlideSize.getX() );
+
+ case ATTRIBUTE_POS_X:
+ return makeGenericAnimation( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isPosXValid,
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ rShape->getBounds().getCenterX(),
+ &ShapeAttributeLayer::getPosX,
+ &ShapeAttributeLayer::setPosX,
+ // convert expression parser value from relative page size
+ rSlideSize.getX() );
+
+ case ATTRIBUTE_POS_Y:
+ return makeGenericAnimation( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isPosYValid,
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ rShape->getBounds().getCenterY(),
+ &ShapeAttributeLayer::getPosY,
+ &ShapeAttributeLayer::setPosY,
+ // convert expression parser value from relative page size
+ rSlideSize.getY() );
+ }
+
+ return NumberAnimationSharedPtr();
+ }
+
+ EnumAnimationSharedPtr AnimationFactory::createEnumPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& /*rSlideSize*/,
+ int nFlags )
+ {
+ // ATTENTION: When changing this map, also the classifyAttributeName() method must
+ // be checked and possibly adapted in their switch statement
+ switch( mapAttributeName( rAttrName ) )
+ {
+ default:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_INVALID:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createEnumPropertyAnimation(): Unknown attribute" );
+ break;
+
+ case ATTRIBUTE_CHAR_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_FONT_NAME:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_DIMCOLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_VISIBILITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_WEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_ROTATION:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_OPACITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_ROTATE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_WIDTH:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_Y:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createEnumPropertyAnimation(): Attribute type mismatch" );
+ break;
+
+
+ case ATTRIBUTE_FILL_STYLE:
+ return makeGenericAnimation<EnumAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isFillStyleValid,
+ sal::static_int_cast<sal_Int16>(
+ getDefault<drawing::FillStyle>( rShape, rAttrName )),
+ &ShapeAttributeLayer::getFillStyle,
+ &ShapeAttributeLayer::setFillStyle );
+
+ case ATTRIBUTE_LINE_STYLE:
+ return makeGenericAnimation<EnumAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isLineStyleValid,
+ sal::static_int_cast<sal_Int16>(
+ getDefault<drawing::LineStyle>( rShape, rAttrName )),
+ &ShapeAttributeLayer::getLineStyle,
+ &ShapeAttributeLayer::setLineStyle );
+
+ case ATTRIBUTE_CHAR_POSTURE:
+ return makeGenericAnimation<EnumAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isCharPostureValid,
+ sal::static_int_cast<sal_Int16>(
+ getDefault<awt::FontSlant>( rShape, rAttrName )),
+ &ShapeAttributeLayer::getCharPosture,
+ &ShapeAttributeLayer::setCharPosture );
+
+ case ATTRIBUTE_CHAR_UNDERLINE:
+ return makeGenericAnimation<EnumAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isUnderlineModeValid,
+ getDefault<sal_Int16>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getUnderlineMode,
+ &ShapeAttributeLayer::setUnderlineMode );
+ }
+
+ return EnumAnimationSharedPtr();
+ }
+
+ ColorAnimationSharedPtr AnimationFactory::createColorPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& /*rSlideSize*/,
+ int nFlags )
+ {
+ // ATTENTION: When changing this map, also the classifyAttributeName() method must
+ // be checked and possibly adapted in their switch statement
+ switch( mapAttributeName( rAttrName ) )
+ {
+ default:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_INVALID:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createColorPropertyAnimation(): Unknown attribute" );
+ break;
+
+ case ATTRIBUTE_CHAR_FONT_NAME:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_POSTURE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_ROTATION:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_UNDERLINE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_WEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_OPACITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_ROTATE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_VISIBILITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_WIDTH:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_Y:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createColorPropertyAnimation(): Attribute type mismatch" );
+ break;
+
+ case ATTRIBUTE_CHAR_COLOR:
+ return makeGenericAnimation<ColorAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isCharColorValid,
+ getDefault<RGBColor>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getCharColor,
+ &ShapeAttributeLayer::setCharColor );
+
+ case ATTRIBUTE_COLOR:
+ // TODO(F2): This is just mapped to fill color to make it work
+ return makeGenericAnimation<ColorAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isFillColorValid,
+ getDefault<RGBColor>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getFillColor,
+ &ShapeAttributeLayer::setFillColor );
+
+ case ATTRIBUTE_DIMCOLOR:
+ return makeGenericAnimation<ColorAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isDimColorValid,
+ getDefault<RGBColor>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getDimColor,
+ &ShapeAttributeLayer::setDimColor );
+
+ case ATTRIBUTE_FILL_COLOR:
+ return makeGenericAnimation<ColorAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isFillColorValid,
+ getDefault<RGBColor>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getFillColor,
+ &ShapeAttributeLayer::setFillColor );
+
+ case ATTRIBUTE_LINE_COLOR:
+ return makeGenericAnimation<ColorAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isLineColorValid,
+ getDefault<RGBColor>( rShape, rAttrName ),
+ &ShapeAttributeLayer::getLineColor,
+ &ShapeAttributeLayer::setLineColor );
+ }
+
+ return ColorAnimationSharedPtr();
+ }
+
+ PairAnimationSharedPtr AnimationFactory::createPairPropertyAnimation( const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ sal_Int16 nTransformType,
+ int nFlags )
+ {
+ const ::basegfx::B2DRectangle& rBounds( rShape->getBounds() );
+
+ switch( nTransformType )
+ {
+ case animations::AnimationTransformType::SCALE:
+ return PairAnimationSharedPtr(
+ new TupleAnimation< ::basegfx::B2DSize >(
+ rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isWidthValid,
+ &ShapeAttributeLayer::isHeightValid,
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ rBounds.getRange(),
+ rBounds.getRange(),
+ &ShapeAttributeLayer::getWidth,
+ &ShapeAttributeLayer::getHeight,
+ &ShapeAttributeLayer::setSize ) );
+
+ case animations::AnimationTransformType::TRANSLATE:
+ return PairAnimationSharedPtr(
+ new TupleAnimation< ::basegfx::B2DPoint >(
+ rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isPosXValid,
+ &ShapeAttributeLayer::isPosYValid,
+ // TODO(F1): Check whether _shape_ bounds are correct here.
+ // Theoretically, our AttrLayer is way down the stack, and
+ // we only have to consider _that_ value, not the one from
+ // the top of the stack as returned by Shape::getBounds()
+ rBounds.getCenter(),
+ rSlideSize,
+ &ShapeAttributeLayer::getPosX,
+ &ShapeAttributeLayer::getPosY,
+ &ShapeAttributeLayer::setPosition ) );
+
+ default:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createPairPropertyAnimation(): Attribute type mismatch" );
+ break;
+ }
+
+ return PairAnimationSharedPtr();
+ }
+
+ StringAnimationSharedPtr AnimationFactory::createStringPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& /*rSlideSize*/,
+ int nFlags )
+ {
+ // ATTENTION: When changing this map, also the classifyAttributeName() method must
+ // be checked and possibly adapted in their switch statement
+ switch( mapAttributeName( rAttrName ) )
+ {
+ default:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_INVALID:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createStringPropertyAnimation(): Unknown attribute" );
+ break;
+
+ case ATTRIBUTE_CHAR_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_ROTATION:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_UNDERLINE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_DIMCOLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_OPACITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_ROTATE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_VISIBILITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_WIDTH:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_POSTURE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_WEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_STYLE:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createStringPropertyAnimation(): Attribute type mismatch" );
+ break;
+
+ case ATTRIBUTE_CHAR_FONT_NAME:
+ return makeGenericAnimation<StringAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isFontFamilyValid,
+ getDefault< ::rtl::OUString >( rShape, rAttrName ),
+ &ShapeAttributeLayer::getFontFamily,
+ &ShapeAttributeLayer::setFontFamily );
+ }
+
+ return StringAnimationSharedPtr();
+ }
+
+ BoolAnimationSharedPtr AnimationFactory::createBoolPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& /*rShape*/,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& /*rSlideSize*/,
+ int nFlags )
+ {
+ // ATTENTION: When changing this map, also the classifyAttributeName() method must
+ // be checked and possibly adapted in their switch statement
+ switch( mapAttributeName( rAttrName ) )
+ {
+ default:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_INVALID:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createBoolPropertyAnimation(): Unknown attribute" );
+ break;
+
+ case ATTRIBUTE_CHAR_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_FONT_NAME:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_POSTURE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_ROTATION:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_WEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_DIMCOLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_FILL_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_HEIGHT:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_COLOR:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_LINE_STYLE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_OPACITY:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_ROTATE:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_SKEW_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_WIDTH:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_X:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_POS_Y:
+ // FALLTHROUGH intended
+ case ATTRIBUTE_CHAR_UNDERLINE:
+ ENSURE_OR_THROW( false,
+ "AnimationFactory::createBoolPropertyAnimation(): Attribute type mismatch" );
+ break;
+
+ case ATTRIBUTE_VISIBILITY:
+ return makeGenericAnimation<BoolAnimation>( rShapeManager,
+ nFlags,
+ &ShapeAttributeLayer::isVisibilityValid,
+ // TODO(F1): Is there a corresponding shape property?
+ true,
+ &ShapeAttributeLayer::getVisibility,
+ &ShapeAttributeLayer::setVisibility );
+ }
+
+ return BoolAnimationSharedPtr();
+ }
+
+ NumberAnimationSharedPtr AnimationFactory::createPathMotionAnimation( const ::rtl::OUString& rSVGDPath,
+ sal_Int16 nAdditive,
+ const AnimatableShapeSharedPtr& /*rShape*/,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags )
+ {
+ return NumberAnimationSharedPtr(
+ new PathAnimation( rSVGDPath, nAdditive,
+ rShapeManager,
+ rSlideSize,
+ nFlags ) );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationaudionode.cxx b/slideshow/source/engine/animationnodes/animationaudionode.cxx
new file mode 100644
index 000000000000..a03336650459
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationaudionode.cxx
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "eventqueue.hxx"
+#include "animationaudionode.hxx"
+#include "delayevent.hxx"
+#include "tools.hxx"
+#include "nodetools.hxx"
+#include "boost/bind.hpp"
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+AnimationAudioNode::AnimationAudioNode(
+ const uno::Reference< animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : BaseNode( xNode, rParent, rContext ),
+ mxAudioNode( xNode, uno::UNO_QUERY_THROW ),
+ maSoundURL(),
+ mpPlayer()
+{
+ mxAudioNode->getSource() >>= maSoundURL;
+
+ OSL_ENSURE( maSoundURL.getLength(),
+ "could not extract sound source URL/empty URL string" );
+
+ ENSURE_OR_THROW( getContext().mxComponentContext.is(),
+ "Invalid component context" );
+}
+
+void AnimationAudioNode::dispose()
+{
+ resetPlayer();
+ mxAudioNode.clear();
+ BaseNode::dispose();
+}
+
+void AnimationAudioNode::activate_st()
+{
+ createPlayer();
+
+ AnimationEventHandlerSharedPtr aHandler(
+ boost::dynamic_pointer_cast<AnimationEventHandler>( getSelf() ) );
+ OSL_ENSURE( aHandler,
+ "could not cast self to AnimationEventHandler?" );
+ getContext().mrEventMultiplexer.addCommandStopAudioHandler( aHandler );
+
+ if (mpPlayer && mpPlayer->startPlayback())
+ {
+ // TODO(F2): Handle end time attribute, too
+ if( getXAnimationNode()->getDuration().hasValue() )
+ {
+ scheduleDeactivationEvent();
+ }
+ else
+ {
+ // no node duration. Take inherent media time, then
+ scheduleDeactivationEvent(
+ makeDelay( boost::bind( &AnimationNode::deactivate, getSelf() ),
+ mpPlayer->getDuration(),
+ "AnimationAudioNode::deactivate with delay") );
+ }
+ }
+ else
+ {
+ // deactivate ASAP:
+ scheduleDeactivationEvent(
+ makeEvent( boost::bind( &AnimationNode::deactivate, getSelf() ),
+ "AnimationAudioNode::deactivate without delay") );
+ }
+}
+
+// TODO(F2): generate deactivation event, when sound
+// is over
+
+void AnimationAudioNode::deactivate_st( NodeState /*eDestState*/ )
+{
+ AnimationEventHandlerSharedPtr aHandler(
+ boost::dynamic_pointer_cast<AnimationEventHandler>( getSelf() ) );
+ OSL_ENSURE( aHandler,
+ "could not cas self to AnimationEventHandler?" );
+ getContext().mrEventMultiplexer.removeCommandStopAudioHandler( aHandler );
+
+ // force-end sound
+ if (mpPlayer)
+ {
+ mpPlayer->stopPlayback();
+ resetPlayer();
+ }
+
+ // notify _after_ state change:
+ getContext().mrEventQueue.addEvent(
+ makeEvent( boost::bind( &EventMultiplexer::notifyAudioStopped,
+ boost::ref(getContext().mrEventMultiplexer),
+ getSelf() ),
+ "AnimationAudioNode::notifyAudioStopped") );
+}
+
+bool AnimationAudioNode::hasPendingAnimation() const
+{
+ // force slide to use the animation framework
+ // (otherwise, a single sound on the slide would
+ // not be played).
+ return true;
+}
+
+void AnimationAudioNode::createPlayer() const
+{
+ if (mpPlayer)
+ return;
+
+ try
+ {
+ mpPlayer = SoundPlayer::create( getContext().mrEventMultiplexer,
+ maSoundURL,
+ getContext().mxComponentContext );
+ }
+ catch( lang::NoSupportException& )
+ {
+ // catch possible exceptions from SoundPlayer,
+ // since being not able to playback the sound
+ // is not a hard error here (remainder of the
+ // animations should still work).
+ }
+}
+
+void AnimationAudioNode::resetPlayer() const
+{
+ if (mpPlayer)
+ {
+ mpPlayer->stopPlayback();
+ mpPlayer->dispose();
+ mpPlayer.reset();
+ }
+}
+
+bool AnimationAudioNode::handleAnimationEvent(
+ const AnimationNodeSharedPtr& /*rNode*/ )
+{
+ // TODO(F2): for now we support only STOPAUDIO events.
+ deactivate();
+ return true;
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationaudionode.hxx b/slideshow/source/engine/animationnodes/animationaudionode.hxx
new file mode 100644
index 000000000000..35397557d0e2
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationaudionode.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONAUDIONODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONAUDIONODE_HXX
+
+#include "basecontainernode.hxx"
+#include "soundplayer.hxx"
+#include "com/sun/star/animations/XAnimationNode.hpp"
+#include "com/sun/star/animations/XAudio.hpp"
+
+namespace slideshow {
+namespace internal {
+
+/** Audio node.
+
+ This animation node contains an audio effect. Duration and
+ start/stop behaviour is affected by the referenced audio
+ file.
+*/
+class AnimationAudioNode : public BaseNode, public AnimationEventHandler
+{
+public:
+ AnimationAudioNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext );
+
+protected:
+ virtual void dispose();
+
+private:
+ virtual void activate_st();
+ virtual void deactivate_st( NodeState eDestState );
+ virtual bool hasPendingAnimation() const;
+
+ /// overriden, because we need to deal with STOPAUDIO commands
+ virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );
+
+private:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAudio > mxAudioNode;
+ ::rtl::OUString maSoundURL;
+ mutable SoundPlayerSharedPtr mpPlayer;
+
+ void createPlayer() const;
+ void resetPlayer() const;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONAUDIONODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationbasenode.cxx b/slideshow/source/engine/animationnodes/animationbasenode.cxx
new file mode 100644
index 000000000000..ee979e60e659
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationbasenode.cxx
@@ -0,0 +1,492 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <comphelper/anytostring.hxx>
+#include <com/sun/star/presentation/ParagraphTarget.hpp>
+#include <com/sun/star/animations/Timing.hpp>
+#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
+#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
+
+#include "nodetools.hxx"
+#include "doctreenode.hxx"
+#include "animationbasenode.hxx"
+#include "delayevent.hxx"
+#include "framerate.hxx"
+
+#include <boost/bind.hpp>
+#include <boost/optional.hpp>
+#include <algorithm>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+AnimationBaseNode::AnimationBaseNode(
+ const uno::Reference< animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : BaseNode( xNode, rParent, rContext ),
+ mxAnimateNode( xNode, uno::UNO_QUERY_THROW ),
+ maAttributeLayerHolder(),
+ maSlideSize( rContext.maSlideSize ),
+ mpActivity(),
+ mpShape(),
+ mpShapeSubset(),
+ mpSubsetManager(rContext.maContext.mpSubsettableShapeManager),
+ mbIsIndependentSubset( rContext.mbIsIndependentSubset )
+{
+ // extract native node targets
+ // ===========================
+
+ // plain shape target
+ uno::Reference< drawing::XShape > xShape( mxAnimateNode->getTarget(),
+ uno::UNO_QUERY );
+
+ // distinguish 5 cases:
+ //
+ // - plain shape target
+ // (NodeContext.mpMasterShapeSubset full set)
+ //
+ // - parent-generated subset (generate an
+ // independent subset)
+ //
+ // - parent-generated subset from iteration
+ // (generate a dependent subset)
+ //
+ // - XShape target at the XAnimatioNode (generate
+ // a plain shape target)
+ //
+ // - ParagraphTarget target at the XAnimationNode
+ // (generate an independent shape subset)
+ if( rContext.mpMasterShapeSubset )
+ {
+ if( rContext.mpMasterShapeSubset->isFullSet() )
+ {
+ // case 1: plain shape target from parent
+ mpShape = rContext.mpMasterShapeSubset->getSubsetShape();
+ }
+ else
+ {
+ // cases 2 & 3: subset shape
+ mpShapeSubset = rContext.mpMasterShapeSubset;
+ }
+ }
+ else
+ {
+ // no parent-provided shape, try to extract
+ // from XAnimationNode - cases 4 and 5
+
+ if( xShape.is() )
+ {
+ mpShape = lookupAttributableShape( getContext().mpSubsettableShapeManager,
+ xShape );
+ }
+ else
+ {
+ // no shape provided. Maybe a ParagraphTarget?
+ presentation::ParagraphTarget aTarget;
+
+ if( !(mxAnimateNode->getTarget() >>= aTarget) )
+ ENSURE_OR_THROW(
+ false, "could not extract any target information" );
+
+ xShape = aTarget.Shape;
+
+ ENSURE_OR_THROW( xShape.is(), "invalid shape in ParagraphTarget" );
+
+ mpShape = lookupAttributableShape( getContext().mpSubsettableShapeManager,
+ xShape );
+
+ // NOTE: For shapes with ParagraphTarget, we ignore
+ // the SubItem property. We implicitely assume that it
+ // is set to ONLY_TEXT.
+ OSL_ENSURE(
+ mxAnimateNode->getSubItem() ==
+ presentation::ShapeAnimationSubType::ONLY_TEXT ||
+ mxAnimateNode->getSubItem() ==
+ presentation::ShapeAnimationSubType::AS_WHOLE,
+ "ParagraphTarget given, but subitem not AS_TEXT or AS_WHOLE? "
+ "Make up your mind, I'll ignore the subitem." );
+
+ // okay, found a ParagraphTarget with a valid XShape. Does the shape
+ // provide the given paragraph?
+ const DocTreeNode& rTreeNode(
+ mpShape->getTreeNodeSupplier().getTreeNode(
+ aTarget.Paragraph,
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) );
+
+ // CAUTION: the creation of the subset shape
+ // _must_ stay in the node constructor, since
+ // Slide::prefetchShow() initializes shape
+ // attributes right after animation import (or
+ // the Slide class must be changed).
+ mpShapeSubset.reset(
+ new ShapeSubset( mpShape,
+ rTreeNode,
+ mpSubsetManager ));
+
+ // Override NodeContext, and flag this node as
+ // a special independent subset one. This is
+ // important when applying initial attributes:
+ // independent shape subsets must be setup
+ // when the slide starts, since they, as their
+ // name suggest, can have state independent to
+ // the master shape. The following example
+ // might illustrate that: a master shape has
+ // no effect, one of the text paragraphs
+ // within it has an appear effect. Now, the
+ // respective paragraph must be invisible when
+ // the slide is initially shown, and become
+ // visible only when the effect starts.
+ mbIsIndependentSubset = true;
+
+ // already enable subset right here, the
+ // setup of initial shape attributes of
+ // course needs the subset shape
+ // generated, to apply e.g. visibility
+ // changes.
+ mpShapeSubset->enableSubsetShape();
+ }
+ }
+}
+
+void AnimationBaseNode::dispose()
+{
+ if (mpActivity) {
+ mpActivity->dispose();
+ mpActivity.reset();
+ }
+
+ maAttributeLayerHolder.reset();
+ mxAnimateNode.clear();
+ mpShape.reset();
+ mpShapeSubset.reset();
+
+ BaseNode::dispose();
+}
+
+bool AnimationBaseNode::init_st()
+{
+ // if we've still got an old activity lying around, dispose it:
+ if (mpActivity) {
+ mpActivity->dispose();
+ mpActivity.reset();
+ }
+
+ // note: actually disposing the activity too early might cause problems,
+ // because on dequeued() it calls endAnimation(pAnim->end()), thus ending
+ // animation _after_ last screen update.
+ // review that end() is properly called (which calls endAnimation(), too).
+
+ try {
+ // TODO(F2): For restart functionality, we must regenerate activities,
+ // since they are not able to reset their state (or implement _that_)
+ mpActivity = createActivity();
+ }
+ catch (uno::Exception const&) {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(cppu::getCaughtException()),
+ RTL_TEXTENCODING_UTF8 ) );
+ // catch and ignore. We later handle empty activities, but for
+ // other nodes to function properly, the core functionality of
+ // this node must remain up and running.
+ }
+ return true;
+}
+
+bool AnimationBaseNode::resolve_st()
+{
+ // enable shape subset for automatically generated
+ // subsets. Independent subsets are already setup
+ // during construction time. Doing it only here
+ // saves us a lot of sprites and shapes lying
+ // around. This is especially important for
+ // character-wise iterations, since the shape
+ // content (e.g. thousands of characters) would
+ // otherwise be painted character-by-character.
+ if (isDependentSubsettedShape() && mpShapeSubset) {
+ mpShapeSubset->enableSubsetShape();
+ }
+ return true;
+}
+
+void AnimationBaseNode::activate_st()
+{
+ // create new attribute layer
+ maAttributeLayerHolder.createAttributeLayer( getShape() );
+
+ ENSURE_OR_THROW( maAttributeLayerHolder.get(),
+ "Could not generate shape attribute layer" );
+
+ // TODO(Q2): This affects the way mpActivity
+ // works, but is performed here because of
+ // locality (we're fiddling with the additive mode
+ // here, anyway, and it's the only place where we
+ // do). OTOH, maybe the complete additive mode
+ // setup should be moved to the activities.
+
+ // for simple by-animations, the SMIL spec
+ // requires us to emulate "0,by-value" value list
+ // behaviour, with additive mode forced to "sum",
+ // no matter what the input is
+ // (http://www.w3.org/TR/smil20/animation.html#adef-by).
+ if( mxAnimateNode->getBy().hasValue() &&
+ !mxAnimateNode->getTo().hasValue() &&
+ !mxAnimateNode->getFrom().hasValue() )
+ {
+ // force attribute mode to REPLACE (note the
+ // subtle discrepancy to the paragraph above,
+ // where SMIL requires SUM. This is internally
+ // handled by the FromToByActivity, and is
+ // because otherwise DOM values would not be
+ // handled correctly: the activity cannot
+ // determine whether an
+ // Activity::getUnderlyingValue() yields the
+ // DOM value, or already a summed-up conglomerate)
+ //
+ // Note that this poses problems with our
+ // hybrid activity duration (time or min number of frames),
+ // since if activities
+ // exceed their duration, wrong 'by' start
+ // values might arise ('Laser effect')
+ maAttributeLayerHolder.get()->setAdditiveMode(
+ animations::AnimationAdditiveMode::REPLACE );
+ }
+ else
+ {
+ // apply additive mode to newly created Attribute layer
+ maAttributeLayerHolder.get()->setAdditiveMode(
+ mxAnimateNode->getAdditive() );
+ }
+
+ // fake normal animation behaviour, even if we
+ // show nothing. This is the appropriate way to
+ // handle errors on Activity generation, because
+ // maybe all other effects on the slide are
+ // correctly initialized (but won't run, if we
+ // signal an error here)
+ if (mpActivity) {
+ // supply Activity (and the underlying Animation) with
+ // it's AttributeLayer, to perform the animation on
+ mpActivity->setTargets( getShape(), maAttributeLayerHolder.get() );
+
+ // add to activities queue
+ getContext().mrActivitiesQueue.addActivity( mpActivity );
+ }
+ else {
+ // Actually, DO generate the event for empty activity,
+ // to keep the chain of animations running
+ BaseNode::scheduleDeactivationEvent();
+ }
+}
+
+void AnimationBaseNode::deactivate_st( NodeState eDestState )
+{
+ if (eDestState == FROZEN) {
+ if (mpActivity)
+ mpActivity->end();
+ }
+
+ if (isDependentSubsettedShape()) {
+ // for dependent subsets, remove subset shape
+ // from layer, re-integrate subsetted part
+ // back into original shape. For independent
+ // subsets, we cannot make any assumptions
+ // about subset attribute state relative to
+ // master shape, thus, have to keep it. This
+ // will effectively re-integrate the subsetted
+ // part into the original shape (whose
+ // animation will hopefully have ended, too)
+
+ // this statement will save a whole lot of
+ // sprites for iterated text effects, since
+ // those sprites will only exist during the
+ // actual lifetime of the effects
+ if (mpShapeSubset) {
+ mpShapeSubset->disableSubsetShape();
+ }
+ }
+
+ if (eDestState == ENDED) {
+
+ // no shape anymore, no layer needed:
+ maAttributeLayerHolder.reset();
+
+ if (! isDependentSubsettedShape()) {
+
+ // for all other shapes, removing the
+ // attribute layer quite possibly changes
+ // shape display. Thus, force update
+ AttributableShapeSharedPtr const pShape( getShape() );
+
+ // don't anybody dare to check against
+ // pShape->isVisible() here, removing the
+ // attribute layer might actually make the
+ // shape invisible!
+ getContext().mpSubsettableShapeManager->notifyShapeUpdate( pShape );
+ }
+
+ if (mpActivity) {
+ // kill activity, if still running
+ mpActivity->dispose();
+ mpActivity.reset();
+ }
+ }
+}
+
+bool AnimationBaseNode::hasPendingAnimation() const
+{
+ // TODO(F1): This might not always be true. Are there 'inactive'
+ // animation nodes?
+ return true;
+}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+void AnimationBaseNode::showState() const
+{
+ BaseNode::showState();
+
+ VERBOSE_TRACE( "AnimationBaseNode info: independent subset=%s",
+ mbIsIndependentSubset ? "y" : "n" );
+}
+#endif
+
+ActivitiesFactory::CommonParameters
+AnimationBaseNode::fillCommonParameters() const
+{
+ double nDuration = 0.0;
+
+ // TODO(F3): Duration/End handling is barely there
+ if( !(mxAnimateNode->getDuration() >>= nDuration) ) {
+ mxAnimateNode->getEnd() >>= nDuration; // Wah.
+ }
+
+ // minimal duration we fallback to (avoid 0 here!)
+ nDuration = ::std::max( 0.001, nDuration );
+
+ const bool bAutoReverse( mxAnimateNode->getAutoReverse() );
+
+ boost::optional<double> aRepeats;
+ double nRepeats = 0;
+ if( (mxAnimateNode->getRepeatCount() >>= nRepeats) ) {
+ aRepeats.reset( nRepeats );
+ }
+ else {
+ if( (mxAnimateNode->getRepeatDuration() >>= nRepeats) ) {
+ // when repeatDuration is given,
+ // autoreverse does _not_ modify the
+ // active duration. Thus, calc repeat
+ // count with already adapted simple
+ // duration (twice the specified duration)
+
+ // convert duration back to repeat counts
+ if( bAutoReverse )
+ aRepeats.reset( nRepeats / (2.0 * nDuration) );
+ else
+ aRepeats.reset( nRepeats / nDuration );
+ }
+ else {
+ // no double value for both values - Timing::INDEFINITE?
+ animations::Timing eTiming;
+
+ if( !(mxAnimateNode->getRepeatDuration() >>= eTiming) ||
+ eTiming != animations::Timing_INDEFINITE )
+ {
+ if( !(mxAnimateNode->getRepeatCount() >>= eTiming) ||
+ eTiming != animations::Timing_INDEFINITE )
+ {
+ // no indefinite timing, no other values given -
+ // use simple run, i.e. repeat of 1.0
+ aRepeats.reset( 1.0 );
+ }
+ }
+ }
+ }
+
+ // calc accel/decel:
+ double nAcceleration = 0.0;
+ double nDeceleration = 0.0;
+ BaseNodeSharedPtr const pSelf( getSelf() );
+ for ( boost::shared_ptr<BaseNode> pNode( pSelf );
+ pNode; pNode = pNode->getParentNode() )
+ {
+ uno::Reference<animations::XAnimationNode> const xAnimationNode(
+ pNode->getXAnimationNode() );
+ nAcceleration = std::max( nAcceleration,
+ xAnimationNode->getAcceleration() );
+ nDeceleration = std::max( nDeceleration,
+ xAnimationNode->getDecelerate() );
+ }
+
+ EventSharedPtr pEndEvent;
+ if (pSelf) {
+ pEndEvent = makeEvent(
+ boost::bind( &AnimationNode::deactivate, pSelf ),
+ "AnimationBaseNode::deactivate");
+ }
+
+ // Calculate the minimum frame count that depends on the duration and
+ // the minimum frame count.
+ const sal_Int32 nMinFrameCount (basegfx::clamp<sal_Int32>(
+ basegfx::fround(nDuration * FrameRate::MinimumFramesPerSecond), 1, 10));
+
+ return ActivitiesFactory::CommonParameters(
+ pEndEvent,
+ getContext().mrEventQueue,
+ getContext().mrActivitiesQueue,
+ nDuration,
+ nMinFrameCount,
+ bAutoReverse,
+ aRepeats,
+ nAcceleration,
+ nDeceleration,
+ getShape(),
+ getSlideSize());
+}
+
+AttributableShapeSharedPtr AnimationBaseNode::getShape() const
+{
+ // any subsetting at all?
+ if (mpShapeSubset)
+ return mpShapeSubset->getSubsetShape();
+ else
+ return mpShape; // nope, plain shape always
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationbasenode.hxx b/slideshow/source/engine/animationnodes/animationbasenode.hxx
new file mode 100644
index 000000000000..aac9f3a0c3fe
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationbasenode.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONBASENODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONBASENODE_HXX
+
+#include <com/sun/star/animations/XAnimate.hpp>
+
+#include "basecontainernode.hxx"
+#include "activitiesfactory.hxx"
+#include "shapeattributelayer.hxx"
+#include "shapeattributelayerholder.hxx"
+#include "attributableshape.hxx"
+#include "shapesubset.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** Common base class for all leaf animation nodes.
+
+ This class basically holds the target shape
+*/
+class AnimationBaseNode : public BaseNode
+{
+public:
+ AnimationBaseNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext );
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual void showState() const;
+#endif
+
+protected:
+ virtual void dispose();
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate> const& getXAnimateNode() const
+ { return mxAnimateNode; }
+
+ /// Create parameter struct for ActivitiesFactory
+ ActivitiesFactory::CommonParameters fillCommonParameters() const;
+ ::basegfx::B2DVector const& getSlideSize() const { return maSlideSize; }
+ AttributableShapeSharedPtr getShape() const;
+
+private:
+ virtual bool hasPendingAnimation() const;
+
+private: // state transition callbacks
+ virtual bool init_st();
+ virtual bool resolve_st();
+ virtual void activate_st();
+ virtual void deactivate_st( NodeState eDestState );
+ virtual AnimationActivitySharedPtr createActivity() const = 0;
+
+private:
+ /** Returns true, if this is a subset animation, and
+ the subset is autogenerated (e.g. from an
+ iteration)
+ */
+ bool isDependentSubsettedShape() const
+ { return mpShapeSubset && !mbIsIndependentSubset; }
+
+ ShapeAttributeLayerHolder const & getAttributeLayerHolder() const
+ { return maAttributeLayerHolder; }
+
+private:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate> mxAnimateNode;
+ ShapeAttributeLayerHolder maAttributeLayerHolder;
+ ::basegfx::B2DVector maSlideSize;
+ AnimationActivitySharedPtr mpActivity;
+
+ /// When valid, this node has a plain target shape
+ AttributableShapeSharedPtr mpShape;
+ /// When valid, this is a subsetted target shape
+ ShapeSubsetSharedPtr mpShapeSubset;
+ SubsettableShapeManagerSharedPtr mpSubsetManager;
+ bool mbIsIndependentSubset;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONBASENODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationcolornode.cxx b/slideshow/source/engine/animationnodes/animationcolornode.cxx
new file mode 100644
index 000000000000..5bd25ec26aba
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationcolornode.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <com/sun/star/animations/AnimationColorSpace.hpp>
+
+#include "coloranimation.hxx"
+#include "hslcoloranimation.hxx"
+#include "animationcolornode.hxx"
+#include "animationfactory.hxx"
+#include "activitiesfactory.hxx"
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+/** Little wrapper for HSL to RGB mapping.
+
+ This class implements the HSLColorAnimation interface,
+ internally converting to RGB and forwarding to
+ ColorAnimation.
+*/
+class HSLWrapper : public HSLColorAnimation
+{
+public:
+ HSLWrapper( const ColorAnimationSharedPtr& rAnimation )
+ : mpAnimation( rAnimation )
+ {
+ ENSURE_OR_THROW(
+ mpAnimation,
+ "HSLWrapper::HSLWrapper(): Invalid color animation delegate" );
+ }
+
+ virtual void prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& )
+ {}
+
+ virtual void start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+ {
+ mpAnimation->start( rShape, rAttrLayer );
+ }
+
+ virtual void end()
+ {
+ mpAnimation->end();
+ }
+
+ virtual bool operator()( const HSLColor& rColor )
+ {
+ return (*mpAnimation)( RGBColor( rColor ) );
+ }
+
+ virtual HSLColor getUnderlyingValue() const
+ {
+ return HSLColor( mpAnimation->getUnderlyingValue() );
+ }
+
+private:
+ ColorAnimationSharedPtr mpAnimation;
+};
+
+} // anon namespace
+
+AnimationActivitySharedPtr AnimationColorNode::createActivity() const
+{
+ ActivitiesFactory::CommonParameters aParms( fillCommonParameters() );
+
+ switch( mxColorNode->getColorInterpolation() )
+ {
+ case animations::AnimationColorSpace::RGB:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createColorPropertyAnimation(
+ mxColorNode->getAttributeName(),
+ getShape(),
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ getXAnimateNode() );
+
+ case animations::AnimationColorSpace::HSL:
+ // Wrap a plain ColorAnimation with the HSL
+ // wrapper, which implements the HSLColorAnimation
+ // interface, and internally converts HSL to RGB color
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ HSLColorAnimationSharedPtr(
+ new HSLWrapper(
+ AnimationFactory::createColorPropertyAnimation(
+ mxColorNode->getAttributeName(),
+ getShape(),
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ))),
+ mxColorNode );
+
+ default:
+ ENSURE_OR_THROW( false, "AnimationColorNode::createColorActivity(): "
+ "Unexpected color space" );
+ }
+
+ return AnimationActivitySharedPtr();
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationcolornode.hxx b/slideshow/source/engine/animationnodes/animationcolornode.hxx
new file mode 100644
index 000000000000..dfa9f60cfa82
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationcolornode.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONCOLORNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONCOLORNODE_HXX
+
+#include "animationbasenode.hxx"
+#include "com/sun/star/animations/XAnimateColor.hpp"
+
+namespace slideshow {
+namespace internal {
+
+class AnimationColorNode : public AnimationBaseNode
+{
+public:
+ AnimationColorNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext )
+ : AnimationBaseNode( xNode, pParent, rContext ),
+ mxColorNode( xNode, ::com::sun::star::uno::UNO_QUERY_THROW ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const { return "AnimationColorNode"; }
+#endif
+
+private:
+ virtual AnimationActivitySharedPtr createActivity() const;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimateColor > mxColorNode;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONCOLORNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationcommandnode.cxx b/slideshow/source/engine/animationnodes/animationcommandnode.cxx
new file mode 100644
index 000000000000..6717b5fd7a38
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationcommandnode.cxx
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <com/sun/star/presentation/EffectCommands.hpp>
+#include <com/sun/star/animations/XAnimate.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include "animationcommandnode.hxx"
+#include "delayevent.hxx"
+#include "tools.hxx"
+#include "nodetools.hxx"
+
+#include <boost/bind.hpp>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace EffectCommands = com::sun::star::presentation::EffectCommands;
+
+AnimationCommandNode::AnimationCommandNode( uno::Reference<animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext ) :
+ BaseNode( xNode, pParent, rContext ),
+ mpShape(),
+ mxCommandNode( xNode, ::com::sun::star::uno::UNO_QUERY_THROW )
+{
+ uno::Reference< drawing::XShape > xShape( mxCommandNode->getTarget(),
+ uno::UNO_QUERY );
+ ShapeSharedPtr pShape( getContext().mpSubsettableShapeManager->lookupShape( xShape ) );
+ mpShape = ::boost::dynamic_pointer_cast< ExternalMediaShape >( pShape );
+}
+
+void AnimationCommandNode::dispose()
+{
+ mxCommandNode.clear();
+ mpShape.reset();
+ BaseNode::dispose();
+}
+
+void AnimationCommandNode::activate_st()
+{
+ switch( mxCommandNode->getCommand() ) {
+ // the command is user defined
+ case EffectCommands::CUSTOM: break;
+ // the command is an ole verb.
+ case EffectCommands::VERB: break;
+ // the command starts playing on a media object
+ case EffectCommands::PLAY:
+ {
+ double fMediaTime=0.0;
+ beans::PropertyValue aMediaTime;
+ if( (mxCommandNode->getParameter() >>= aMediaTime) &&
+ aMediaTime.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("MediaTime") ))
+ {
+ aMediaTime.Value >>= fMediaTime;
+ }
+ if( mpShape )
+ {
+ mpShape->setMediaTime(fMediaTime/1000.0);
+ mpShape->play();
+ }
+ break;
+ }
+ // the command toggles the pause status on a media object
+ case EffectCommands::TOGGLEPAUSE:
+ {
+ if( mpShape )
+ {
+ if( mpShape->isPlaying() )
+ mpShape->pause();
+ else
+ mpShape->play();
+ }
+ break;
+ }
+ // the command stops the animation on a media object
+ case EffectCommands::STOP:
+ {
+ if( mpShape )
+ mpShape->stop();
+ break;
+ }
+ // the command stops all currently running sound effects
+ case EffectCommands::STOPAUDIO:
+ getContext().mrEventMultiplexer.notifyCommandStopAudio( getSelf() );
+ break;
+ }
+
+ // deactivate ASAP:
+ scheduleDeactivationEvent(
+ makeEvent( boost::bind( &AnimationNode::deactivate, getSelf() ),
+ "AnimationCommandNode::deactivate" ) );
+}
+
+bool AnimationCommandNode::hasPendingAnimation() const
+{
+ return mxCommandNode->getCommand() == EffectCommands::STOPAUDIO || mpShape;
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationcommandnode.hxx b/slideshow/source/engine/animationnodes/animationcommandnode.hxx
new file mode 100644
index 000000000000..94b10fd44e93
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationcommandnode.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONCOMMANDNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONCOMMANDNODE_HXX
+
+#include "basecontainernode.hxx"
+#include "externalmediashape.hxx"
+#include "soundplayer.hxx"
+#include "com/sun/star/animations/XCommand.hpp"
+
+namespace slideshow {
+namespace internal {
+
+/** Command node.
+
+ This animation node encapsulates a command. Not yet implemented:
+ verb & custom.
+*/
+class AnimationCommandNode : public BaseNode
+{
+public:
+ AnimationCommandNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext );
+
+protected:
+ virtual void dispose();
+
+private:
+ virtual void activate_st();
+ virtual bool hasPendingAnimation() const;
+
+private:
+ ExternalMediaShapeSharedPtr mpShape;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XCommand > mxCommandNode;
+ bool mbIsPaused;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONAUDIONODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationnodefactory.cxx b/slideshow/source/engine/animationnodes/animationnodefactory.cxx
new file mode 100644
index 000000000000..7e2f3bb4d59e
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationnodefactory.cxx
@@ -0,0 +1,622 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/animations/XAnimate.hpp>
+#include <com/sun/star/animations/AnimationNodeType.hpp>
+#include <com/sun/star/presentation/EffectNodeType.hpp>
+#include <com/sun/star/presentation/TextAnimationType.hpp>
+#include <com/sun/star/animations/XAnimateSet.hpp>
+#include <com/sun/star/animations/XIterateContainer.hpp>
+#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
+#include <com/sun/star/animations/XAnimateMotion.hpp>
+#include <com/sun/star/animations/XAnimateColor.hpp>
+#include <com/sun/star/animations/XAnimateTransform.hpp>
+#include <com/sun/star/animations/AnimationTransformType.hpp>
+#include <com/sun/star/animations/XTransitionFilter.hpp>
+#include <com/sun/star/animations/XAudio.hpp>
+#include <com/sun/star/presentation/ParagraphTarget.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <animations/animationnodehelper.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "animationnodefactory.hxx"
+#include "paralleltimecontainer.hxx"
+#include "sequentialtimecontainer.hxx"
+#include "propertyanimationnode.hxx"
+#include "animationsetnode.hxx"
+#include "animationpathmotionnode.hxx"
+#include "animationcolornode.hxx"
+#include "animationtransformnode.hxx"
+#include "animationtransitionfilternode.hxx"
+#include "animationaudionode.hxx"
+#include "animationcommandnode.hxx"
+#include "nodetools.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+
+using namespace ::com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+// forward declaration needed by NodeCreator
+BaseNodeSharedPtr implCreateAnimationNode(
+ const uno::Reference< animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext );
+
+class NodeCreator
+{
+public:
+ NodeCreator( BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : mrParent( rParent ), mrContext( rContext ) {}
+
+ void operator()(
+ const uno::Reference< animations::XAnimationNode >& xChildNode ) const
+ {
+ createChild( xChildNode, mrContext );
+ }
+
+protected:
+ void createChild(
+ const uno::Reference< animations::XAnimationNode >& xChildNode,
+ const NodeContext& rContext ) const
+ {
+ BaseNodeSharedPtr pChild( implCreateAnimationNode( xChildNode,
+ mrParent,
+ rContext ) );
+
+ OSL_ENSURE( pChild,
+ "NodeCreator::operator(): child creation failed" );
+
+ // TODO(Q1): This yields circular references, which, it seems, is
+ // unavoidable here
+ if( pChild )
+ mrParent->appendChildNode( pChild );
+ }
+
+ BaseContainerNodeSharedPtr& mrParent;
+ const NodeContext& mrContext;
+};
+
+/** Same as NodeCreator, only that NodeContext's
+ SubsetShape is cloned for every child node.
+
+ This is used for iterated animation node generation
+*/
+class CloningNodeCreator : private NodeCreator
+{
+public:
+ CloningNodeCreator( BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : NodeCreator( rParent, rContext ) {}
+
+ void operator()(
+ const uno::Reference< animations::XAnimationNode >& xChildNode ) const
+ {
+ NodeContext aContext( mrContext );
+
+ // TODO(Q1): There's a catch here. If you clone a
+ // subset whose actual subsetting has already been
+ // realized (i.e. if enableSubsetShape() has been
+ // called already), and the original of your clone
+ // goes out of scope, then your subset will be
+ // gone (SubsettableShapeManager::revokeSubset() be
+ // called). As of now, this behaviour is not
+ // triggered here (we either clone, XOR we enable
+ // subset initially), but one might consider
+ // reworking DrawShape/ShapeSubset to avoid this.
+
+ // clone ShapeSubset, since each node needs their
+ // own version of the ShapeSubset (otherwise,
+ // e.g. activity counting does not work - subset
+ // would be removed after first animation node
+ // disables it).
+ //
+ // NOTE: this is only a problem for animation
+ // nodes that explicitely call
+ // disableSubsetShape(). Independent shape subsets
+ // (like those created for ParagraphTargets)
+ // solely rely on the ShapeSubset destructor to
+ // normalize things, which does the right thing
+ // here: the subset is only removed after _the
+ // last_ animation node releases the shared ptr.
+ aContext.mpMasterShapeSubset.reset(
+ new ShapeSubset( *aContext.mpMasterShapeSubset ) );
+
+ createChild( xChildNode, aContext );
+ }
+};
+
+/** Create animation nodes for text iterations
+
+ This method clones the animation nodes below xIterNode
+ for every iterated shape entity.
+*/
+bool implCreateIteratedNodes(
+ const uno::Reference< animations::XIterateContainer >& xIterNode,
+ BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+{
+ ENSURE_OR_THROW( xIterNode.is(),
+ "implCreateIteratedNodes(): Invalid node" );
+
+ const double nIntervalTimeout( xIterNode->getIterateInterval() );
+
+ // valid iterate interval? We're ruling out monstrous
+ // values here, to avoid pseudo 'hangs' in the
+ // presentation
+ if( nIntervalTimeout < 0.0 ||
+ nIntervalTimeout > 1000.0 )
+ {
+ return false; // not an active iteration
+ }
+
+ if( ::basegfx::fTools::equalZero( nIntervalTimeout ) )
+ OSL_TRACE( "implCreateIteratedNodes(): "
+ "iterate interval close to zero, there's "
+ "no point in defining such an effect "
+ "(visually equivalent to whole-shape effect)" );
+
+ // Determine target shape (or subset)
+ // ==================================
+
+ // TODO(E1): I'm not too sure what to expect here...
+ ENSURE_OR_RETURN_FALSE(
+ xIterNode->getTarget().hasValue(),
+ "implCreateIteratedNodes(): no target on ITERATE node" );
+
+ uno::Reference< drawing::XShape > xTargetShape( xIterNode->getTarget(),
+ uno::UNO_QUERY );
+
+ presentation::ParagraphTarget aTarget;
+ sal_Int16 nSubItem( xIterNode->getSubItem() );
+ bool bParagraphTarget( false );
+
+ if( !xTargetShape.is() )
+ {
+ // no shape provided. Maybe a ParagraphTarget?
+ if( !(xIterNode->getTarget() >>= aTarget) )
+ ENSURE_OR_RETURN_FALSE(
+ false,
+ "implCreateIteratedNodes(): could not extract any "
+ "target information" );
+
+ xTargetShape = aTarget.Shape;
+
+ ENSURE_OR_RETURN_FALSE(
+ xTargetShape.is(),
+ "implCreateIteratedNodes(): invalid shape in ParagraphTarget" );
+
+ // we've a paragraph target to iterate over, thus,
+ // the whole animation container refers only to
+ // the text
+ nSubItem = presentation::ShapeAnimationSubType::ONLY_TEXT;
+
+ bParagraphTarget = true;
+ }
+
+ // Lookup shape, and fill NodeContext
+ // ==================================
+
+ AttributableShapeSharedPtr pTargetShape(
+ lookupAttributableShape( rContext.maContext.mpSubsettableShapeManager,
+ xTargetShape ) );
+
+ const DocTreeNodeSupplier& rTreeNodeSupplier(
+ pTargetShape->getTreeNodeSupplier() );
+
+ ShapeSubsetSharedPtr pTargetSubset;
+
+ NodeContext aContext( rContext );
+
+ // paragraph targets already need a subset as the
+ // master shape (they're representing only a single
+ // paragraph)
+ if( bParagraphTarget )
+ {
+ ENSURE_OR_RETURN_FALSE(
+ aTarget.Paragraph >= 0 &&
+ rTreeNodeSupplier.getNumberOfTreeNodes(
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) > aTarget.Paragraph,
+ "implCreateIteratedNodes(): paragraph index out of range" );
+
+ pTargetSubset.reset(
+ new ShapeSubset(
+ pTargetShape,
+ // retrieve index aTarget.Paragraph of
+ // type PARAGRAPH from this shape
+ rTreeNodeSupplier.getTreeNode(
+ aTarget.Paragraph,
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ),
+ rContext.maContext.mpSubsettableShapeManager ) );
+
+ // iterate target is not the whole shape, but only
+ // the selected paragraph - subset _must_ be
+ // independent, to be able to affect visibility
+ // independent of master shape
+ aContext.mbIsIndependentSubset = true;
+
+ // already enable parent subset right here, to
+ // make potentially generated subsets subtract
+ // their content from the parent subset (and not
+ // the original shape). Otherwise, already
+ // subsetted parents (e.g. paragraphs) would not
+ // have their characters removed, when the child
+ // iterations start.
+ // Furthermore, the setup of initial shape
+ // attributes of course needs the subset shape
+ // generated, to apply e.g. visibility changes.
+ pTargetSubset->enableSubsetShape();
+ }
+ else
+ {
+ pTargetSubset.reset(
+ new ShapeSubset( pTargetShape,
+ rContext.maContext.mpSubsettableShapeManager ));
+ }
+
+ aContext.mpMasterShapeSubset = pTargetSubset;
+ uno::Reference< animations::XAnimationNode > xNode( xIterNode,
+ uno::UNO_QUERY_THROW );
+
+ // Generate subsets
+ // ================
+
+ if( bParagraphTarget ||
+ nSubItem != presentation::ShapeAnimationSubType::ONLY_TEXT )
+ {
+ // prepend with animations for
+ // full Shape (will be subtracted
+ // from the subset parts within
+ // the Shape::createSubset()
+ // method). For ONLY_TEXT effects,
+ // we skip this part, to animate
+ // only the text.
+ //
+ // OR
+ //
+ // prepend with subset animation for full
+ // _paragraph_, from which the individual
+ // paragraph subsets are subtracted. Note that the
+ // subitem is superfluous here, we always assume
+ // ONLY_TEXT, if a paragraph is referenced as the
+ // master of an iteration effect.
+ NodeCreator aCreator( rParent, aContext );
+ if( !::anim::for_each_childNode( xNode,
+ aCreator ) )
+ {
+ ENSURE_OR_RETURN_FALSE(
+ false,
+ "implCreateIteratedNodes(): iterated child node creation failed" );
+ }
+ }
+
+ // TODO(F2): This does not do the correct
+ // thing. Having nSubItem be set to ONLY_BACKGROUND
+ // should result in the text staying unanimated in the
+ // foreground, while the shape moves in the background
+ // (this behaviour is perfectly possible with the
+ // slideshow engine, only that the text won't be
+ // currently visible, because animations are always in
+ // the foreground)
+ if( nSubItem != presentation::ShapeAnimationSubType::ONLY_BACKGROUND )
+ {
+ // determine type of subitem iteration (logical
+ // text unit to animate)
+ DocTreeNode::NodeType eIterateNodeType(
+ DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL );
+
+ switch( xIterNode->getIterateType() )
+ {
+ case presentation::TextAnimationType::BY_PARAGRAPH:
+ eIterateNodeType = DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH;
+ break;
+
+ case presentation::TextAnimationType::BY_WORD:
+ eIterateNodeType = DocTreeNode::NODETYPE_LOGICAL_WORD;
+ break;
+
+ case presentation::TextAnimationType::BY_LETTER:
+ eIterateNodeType = DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL;
+ break;
+
+ default:
+ ENSURE_OR_THROW(
+ false, "implCreateIteratedNodes(): "
+ "Unexpected IterateType on XIterateContainer");
+ break;
+ }
+
+ if( bParagraphTarget &&
+ eIterateNodeType != DocTreeNode::NODETYPE_LOGICAL_WORD &&
+ eIterateNodeType != DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL )
+ {
+ // will not animate the whole paragraph, when
+ // only the paragraph is animated at all.
+ OSL_ENSURE( false,
+ "implCreateIteratedNodes(): Ignoring paragraph iteration for paragraph master" );
+ }
+ else
+ {
+ // setup iteration parameters
+ // --------------------------
+
+ // iterate target is the whole shape (or the
+ // whole parent subshape), thus, can save
+ // loads of subset shapes by generating them
+ // only when the effects become active -
+ // before and after the effect active
+ // duration, all attributes are shared by
+ // master shape and subset (since the iterated
+ // effects are all the same).
+ aContext.mbIsIndependentSubset = false;
+
+ // determine number of nodes for given subitem
+ // type
+ sal_Int32 nTreeNodes( 0 );
+ if( bParagraphTarget )
+ {
+ // create the iterated subset _relative_ to
+ // the given paragraph index (i.e. animate the
+ // given subset type, but only when it's part
+ // of the given paragraph)
+ nTreeNodes = rTreeNodeSupplier.getNumberOfSubsetTreeNodes(
+ pTargetSubset->getSubset(),
+ eIterateNodeType );
+ }
+ else
+ {
+ // generate normal subset
+ nTreeNodes = rTreeNodeSupplier.getNumberOfTreeNodes(
+ eIterateNodeType );
+ }
+
+
+ // iterate node, generate copies of the children for each subset
+ // -------------------------------------------------------------
+
+ // NodeContext::mnStartDelay contains additional node delay.
+ // This will make the duplicated nodes for each iteration start
+ // increasingly later.
+ aContext.mnStartDelay = nIntervalTimeout;
+
+ for( sal_Int32 i=0; i<nTreeNodes; ++i )
+ {
+ // create subset with the corresponding tree nodes
+ if( bParagraphTarget )
+ {
+ // create subsets relative to paragraph subset
+ aContext.mpMasterShapeSubset.reset(
+ new ShapeSubset(
+ pTargetSubset,
+ rTreeNodeSupplier.getSubsetTreeNode(
+ pTargetSubset->getSubset(),
+ i,
+ eIterateNodeType ) ) );
+ }
+ else
+ {
+ // create subsets from main shape
+ aContext.mpMasterShapeSubset.reset(
+ new ShapeSubset( pTargetSubset,
+ rTreeNodeSupplier.getTreeNode(
+ i,
+ eIterateNodeType ) ) );
+ }
+
+ CloningNodeCreator aCreator( rParent, aContext );
+ if( !::anim::for_each_childNode( xNode,
+ aCreator ) )
+ {
+ ENSURE_OR_RETURN_FALSE(
+ false, "implCreateIteratedNodes(): "
+ "iterated child node creation failed" );
+ }
+
+ aContext.mnStartDelay += nIntervalTimeout;
+ }
+ }
+ }
+
+ // done with iterate child generation
+ return true;
+}
+
+BaseNodeSharedPtr implCreateAnimationNode(
+ const uno::Reference< animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+{
+ ENSURE_OR_THROW( xNode.is(),
+ "implCreateAnimationNode(): invalid XAnimationNode" );
+
+ BaseNodeSharedPtr pCreatedNode;
+ BaseContainerNodeSharedPtr pCreatedContainer;
+
+ // create the internal node, corresponding to xNode
+ switch( xNode->getType() )
+ {
+ case animations::AnimationNodeType::CUSTOM:
+ OSL_ENSURE( false, "implCreateAnimationNode(): "
+ "CUSTOM not yet implemented" );
+ return pCreatedNode;
+
+ case animations::AnimationNodeType::PAR:
+ pCreatedNode = pCreatedContainer = BaseContainerNodeSharedPtr(
+ new ParallelTimeContainer( xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::ITERATE:
+ // map iterate container to ParallelTimeContainer.
+ // the iterating functionality is to be found
+ // below, (see method implCreateIteratedNodes)
+ pCreatedNode = pCreatedContainer = BaseContainerNodeSharedPtr(
+ new ParallelTimeContainer( xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::SEQ:
+ pCreatedNode = pCreatedContainer = BaseContainerNodeSharedPtr(
+ new SequentialTimeContainer( xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::ANIMATE:
+ pCreatedNode.reset( new PropertyAnimationNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::SET:
+ pCreatedNode.reset( new AnimationSetNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::ANIMATEMOTION:
+ pCreatedNode.reset( new AnimationPathMotionNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::ANIMATECOLOR:
+ pCreatedNode.reset( new AnimationColorNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::ANIMATETRANSFORM:
+ pCreatedNode.reset( new AnimationTransformNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::TRANSITIONFILTER:
+ pCreatedNode.reset( new AnimationTransitionFilterNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::AUDIO:
+ pCreatedNode.reset( new AnimationAudioNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ case animations::AnimationNodeType::COMMAND:
+ pCreatedNode.reset( new AnimationCommandNode(
+ xNode, rParent, rContext ) );
+ break;
+
+ default:
+ OSL_ENSURE( false, "implCreateAnimationNode(): "
+ "invalid AnimationNodeType" );
+ return pCreatedNode;
+ }
+
+ // TODO(Q1): This yields circular references, which, it seems, is
+ // unavoidable here
+
+ // HACK: node objects need shared_ptr to themselves,
+ // which we pass them here.
+ pCreatedNode->setSelf( pCreatedNode );
+
+ // if we've got a container node object, recursively add
+ // its children
+ if( pCreatedContainer )
+ {
+ uno::Reference< animations::XIterateContainer > xIterNode(
+ xNode, uno::UNO_QUERY );
+
+ // when this node is an XIterateContainer with
+ // active iterations, this method will generate
+ // the appropriate children
+ if( xIterNode.is() )
+ {
+ // note that implCreateIteratedNodes() might
+ // choose not to generate any child nodes
+ // (e.g. when the iterate timeout is outside
+ // sensible limits). Then, no child nodes are
+ // generated at all, since typically, child
+ // node attribute are incomplete for iteration
+ // children.
+ implCreateIteratedNodes( xIterNode,
+ pCreatedContainer,
+ rContext );
+ }
+ else
+ {
+ // no iterate subset node, just plain child generation now
+ NodeCreator aCreator( pCreatedContainer, rContext );
+ if( !::anim::for_each_childNode( xNode, aCreator ) )
+ {
+ OSL_ENSURE( false, "implCreateAnimationNode(): "
+ "child node creation failed" );
+ return BaseNodeSharedPtr();
+ }
+ }
+ }
+
+ return pCreatedNode;
+}
+
+} // anon namespace
+
+AnimationNodeSharedPtr AnimationNodeFactory::createAnimationNode(
+ const uno::Reference< animations::XAnimationNode >& xNode,
+ const ::basegfx::B2DVector& rSlideSize,
+ const SlideShowContext& rContext )
+{
+ ENSURE_OR_THROW(
+ xNode.is(),
+ "AnimationNodeFactory::createAnimationNode(): invalid XAnimationNode" );
+
+ return BaseNodeSharedPtr( implCreateAnimationNode(
+ xNode,
+ BaseContainerNodeSharedPtr(), // no parent
+ NodeContext( rContext,
+ rSlideSize )));
+}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+void AnimationNodeFactory::showTree( AnimationNodeSharedPtr& pRootNode )
+{
+ if( pRootNode )
+ DEBUG_NODES_SHOWTREE( boost::dynamic_pointer_cast<BaseContainerNode>(
+ pRootNode).get() );
+}
+#endif
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationpathmotionnode.cxx b/slideshow/source/engine/animationnodes/animationpathmotionnode.cxx
new file mode 100644
index 000000000000..7e90f3abf692
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationpathmotionnode.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "animationpathmotionnode.hxx"
+#include "animationfactory.hxx"
+
+namespace slideshow {
+namespace internal {
+
+void AnimationPathMotionNode::dispose()
+{
+ mxPathMotionNode.clear();
+ AnimationBaseNode::dispose();
+}
+
+AnimationActivitySharedPtr AnimationPathMotionNode::createActivity() const
+{
+ rtl::OUString aString;
+ ENSURE_OR_THROW( (mxPathMotionNode->getPath() >>= aString),
+ "no string-based SVG:d path found" );
+
+ ActivitiesFactory::CommonParameters const aParms( fillCommonParameters() );
+ return ActivitiesFactory::createSimpleActivity(
+ aParms,
+ AnimationFactory::createPathMotionAnimation(
+ aString,
+ mxPathMotionNode->getAdditive(),
+ getShape(),
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ true );
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationpathmotionnode.hxx b/slideshow/source/engine/animationnodes/animationpathmotionnode.hxx
new file mode 100644
index 000000000000..c0e11d81863c
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationpathmotionnode.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONPATHMOTIONNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONPATHMOTIONNODE_HXX
+
+#include "animationbasenode.hxx"
+#include "com/sun/star/animations/XAnimateMotion.hpp"
+
+namespace slideshow {
+namespace internal {
+
+class AnimationPathMotionNode : public AnimationBaseNode
+{
+public:
+ AnimationPathMotionNode(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : AnimationBaseNode( xNode, rParent, rContext ),
+ mxPathMotionNode( xNode, ::com::sun::star::uno::UNO_QUERY_THROW ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const
+ { return "AnimationPathMotionNode"; }
+#endif
+
+protected:
+ virtual void dispose();
+
+private:
+ virtual AnimationActivitySharedPtr createActivity() const;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimateMotion > mxPathMotionNode;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONPATHMOTIONNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationsetnode.cxx b/slideshow/source/engine/animationnodes/animationsetnode.cxx
new file mode 100644
index 000000000000..5bf744ecb8ff
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationsetnode.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "animationfactory.hxx"
+#include "setactivity.hxx"
+#include "animationsetnode.hxx"
+#include "nodetools.hxx"
+#include "tools.hxx"
+#include "delayevent.hxx"
+
+#include <boost/bind.hpp>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+void AnimationSetNode::implScheduleDeactivationEvent()
+{
+ scheduleDeactivationEvent();
+}
+
+AnimationActivitySharedPtr AnimationSetNode::createActivity() const
+{
+ ActivitiesFactory::CommonParameters aParms( fillCommonParameters() );
+ uno::Reference<animations::XAnimate> const xAnimateNode = getXAnimateNode();
+ rtl::OUString const attrName( xAnimateNode->getAttributeName() );
+ AttributableShapeSharedPtr const pShape( getShape() );
+
+ // make deactivation a two-step procedure. Normally, we
+ // could solely rely on
+ // BaseNode::scheduleDeactivationEvent() to deactivate()
+ // us. Unfortunately, that method on the one hand ignores
+ // indefinite timing, on the other hand generates
+ // zero-timeout delays, which might get fired _before_ our
+ // set activity has taken place. Therefore, we enforce
+ // sequentiality by letting only the set activity schedule
+ // the deactivation event (and AnimationBaseNode
+ // takes care for the fact when mpActivity should be zero).
+
+ // AnimationBaseNode::fillCommonParameters() has set up
+ // immediate deactivation as default when activity ends, but
+ if (! isIndefiniteTiming( xAnimateNode->getDuration() )) {
+ boost::shared_ptr<AnimationSetNode> const pSelf(
+ boost::dynamic_pointer_cast<AnimationSetNode>(getSelf()) );
+ ENSURE_OR_THROW(
+ pSelf, "cannot cast getSelf() to my type!" );
+ aParms.mpEndEvent = makeEvent(
+ boost::bind( &AnimationSetNode::implScheduleDeactivationEvent,
+ pSelf ),
+ "AnimationSetNode::implScheduleDeactivationEvent");
+ }
+
+ switch (AnimationFactory::classifyAttributeName( attrName )) {
+ default:
+ case AnimationFactory::CLASS_UNKNOWN_PROPERTY:
+ ENSURE_OR_THROW(
+ false, "AnimationSetNode::createSetActivity(): "
+ "Unexpected attribute class" );
+ break;
+
+ case AnimationFactory::CLASS_NUMBER_PROPERTY:
+ {
+ NumberAnimation::ValueType aValue;
+
+ ENSURE_OR_THROW(
+ extractValue( aValue,
+ xAnimateNode->getTo(),
+ pShape,
+ getSlideSize() ),
+ "AnimationSetNode::createSetActivity(): "
+ "Could not import numeric to value" );
+
+ return makeSetActivity(
+ aParms,
+ AnimationFactory::createNumberPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ AnimationFactory::FLAG_NO_SPRITE ),
+ aValue );
+ }
+
+ case AnimationFactory::CLASS_ENUM_PROPERTY:
+ {
+ EnumAnimation::ValueType aValue;
+
+ ENSURE_OR_THROW(
+ extractValue( aValue,
+ xAnimateNode->getTo(),
+ pShape,
+ getSlideSize() ),
+ "AnimationSetNode::createSetActivity(): "
+ "Could not import enum to value" );
+
+ return makeSetActivity(
+ aParms,
+ AnimationFactory::createEnumPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ AnimationFactory::FLAG_NO_SPRITE ),
+ aValue );
+ }
+
+ case AnimationFactory::CLASS_COLOR_PROPERTY:
+ {
+ ColorAnimation::ValueType aValue;
+
+ ENSURE_OR_THROW(
+ extractValue( aValue,
+ xAnimateNode->getTo(),
+ pShape,
+ getSlideSize() ),
+ "AnimationSetNode::createSetActivity(): "
+ "Could not import color to value" );
+
+ return makeSetActivity(
+ aParms,
+ AnimationFactory::createColorPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ AnimationFactory::FLAG_NO_SPRITE ),
+ aValue );
+ }
+
+ case AnimationFactory::CLASS_STRING_PROPERTY:
+ {
+ StringAnimation::ValueType aValue;
+
+ ENSURE_OR_THROW(
+ extractValue( aValue,
+ xAnimateNode->getTo(),
+ pShape,
+ getSlideSize() ),
+ "AnimationSetNode::createSetActivity(): "
+ "Could not import string to value" );
+
+ return makeSetActivity(
+ aParms,
+ AnimationFactory::createStringPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ AnimationFactory::FLAG_NO_SPRITE ),
+ aValue );
+ }
+
+ case AnimationFactory::CLASS_BOOL_PROPERTY:
+ {
+ BoolAnimation::ValueType aValue;
+
+ ENSURE_OR_THROW(
+ extractValue( aValue,
+ xAnimateNode->getTo(),
+ pShape,
+ getSlideSize() ),
+ "AnimationSetNode::createSetActivity(): "
+ "Could not import bool to value" );
+
+ return makeSetActivity(
+ aParms,
+ AnimationFactory::createBoolPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ AnimationFactory::FLAG_NO_SPRITE ),
+ aValue );
+ }
+ }
+
+ return AnimationActivitySharedPtr();
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationsetnode.hxx b/slideshow/source/engine/animationnodes/animationsetnode.hxx
new file mode 100644
index 000000000000..f84f831d38cf
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationsetnode.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX
+
+#include "animationbasenode.hxx"
+
+namespace slideshow {
+namespace internal {
+
+class AnimationSetNode : public AnimationBaseNode
+{
+public:
+ AnimationSetNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext )
+ : AnimationBaseNode( xNode, pParent, rContext ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const { return "AnimationSetNode"; }
+#endif
+
+private:
+ virtual AnimationActivitySharedPtr createActivity() const;
+ void implScheduleDeactivationEvent();
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationtransformnode.cxx b/slideshow/source/engine/animationnodes/animationtransformnode.cxx
new file mode 100644
index 000000000000..fa83ea7fc2da
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationtransformnode.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <com/sun/star/animations/AnimationTransformType.hpp>
+
+#include "animationtransformnode.hxx"
+#include "animationfactory.hxx"
+#include "activitiesfactory.hxx"
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+void AnimationTransformNode::dispose()
+{
+ mxTransformNode.clear();
+ AnimationBaseNode::dispose();
+}
+
+AnimationActivitySharedPtr AnimationTransformNode::createActivity() const
+{
+ ActivitiesFactory::CommonParameters aParms( fillCommonParameters() );
+
+ const sal_Int16 nTransformType( mxTransformNode->getTransformType() );
+
+ const AttributableShapeSharedPtr& rShape( getShape() );
+
+ switch( nTransformType )
+ {
+ default:
+ ENSURE_OR_THROW(
+ false, "AnimationTransformNode::createTransformActivity(): "
+ "Unknown transform type" );
+
+ case animations::AnimationTransformType::TRANSLATE:
+ // FALLTHROUGH intended
+ case animations::AnimationTransformType::SCALE:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createPairPropertyAnimation(
+ rShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ nTransformType ),
+ getXAnimateNode() );
+
+ case animations::AnimationTransformType::ROTATE:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createNumberPropertyAnimation(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Rotate") ),
+ rShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ getXAnimateNode() );
+
+ case animations::AnimationTransformType::SKEWX:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createNumberPropertyAnimation(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("SkewX") ),
+ rShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ getXAnimateNode() );
+
+ case animations::AnimationTransformType::SKEWY:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createNumberPropertyAnimation(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("SkewY") ),
+ rShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ getXAnimateNode() );
+ }
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationtransformnode.hxx b/slideshow/source/engine/animationnodes/animationtransformnode.hxx
new file mode 100644
index 000000000000..c24030f73d41
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationtransformnode.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONTRANSFORMNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONTRANSFORMNODE_HXX
+
+#include "animationbasenode.hxx"
+#include "com/sun/star/animations/XAnimateTransform.hpp"
+
+namespace slideshow {
+namespace internal {
+
+class AnimationTransformNode : public AnimationBaseNode
+{
+public:
+ AnimationTransformNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext )
+ : AnimationBaseNode( xNode, pParent, rContext ),
+ mxTransformNode( xNode, ::com::sun::star::uno::UNO_QUERY_THROW ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const
+ { return "AnimationTransformNode"; }
+#endif
+
+protected:
+ virtual void dispose();
+
+private:
+ virtual AnimationActivitySharedPtr createActivity() const;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimateTransform > mxTransformNode;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONTRANSFORMNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationtransitionfilternode.cxx b/slideshow/source/engine/animationnodes/animationtransitionfilternode.cxx
new file mode 100644
index 000000000000..709685633d25
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationtransitionfilternode.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "animationtransitionfilternode.hxx"
+#include "transitionfactory.hxx"
+
+namespace slideshow {
+namespace internal {
+
+void AnimationTransitionFilterNode::dispose()
+{
+ mxTransitionFilterNode.clear();
+ AnimationBaseNode::dispose();
+}
+
+AnimationActivitySharedPtr
+AnimationTransitionFilterNode::createActivity() const
+{
+ return TransitionFactory::createShapeTransition(
+ fillCommonParameters(),
+ getShape(),
+ getContext().mpSubsettableShapeManager,
+ getSlideSize(),
+ mxTransitionFilterNode );
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/animationtransitionfilternode.hxx b/slideshow/source/engine/animationnodes/animationtransitionfilternode.hxx
new file mode 100644
index 000000000000..05a8802c4ac2
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/animationtransitionfilternode.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONTRANSITIONFILTERNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONTRANSITIONFILTERNODE_HXX
+
+#include "animationbasenode.hxx"
+#include "com/sun/star/animations/XTransitionFilter.hpp"
+
+namespace slideshow {
+namespace internal {
+
+class AnimationTransitionFilterNode : public AnimationBaseNode
+{
+public:
+ AnimationTransitionFilterNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext )
+ : AnimationBaseNode( xNode, pParent, rContext ),
+ mxTransitionFilterNode( xNode, ::com::sun::star::uno::UNO_QUERY_THROW)
+ {}
+
+#if defined(VERBOSE)
+ virtual const char* getDescription() const
+ { return "AnimationTransitionFilterNode"; }
+#endif
+
+protected:
+ virtual void dispose();
+
+private:
+ virtual AnimationActivitySharedPtr createActivity() const;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XTransitionFilter> mxTransitionFilterNode;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONTRANSITIONFILTERNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/basecontainernode.cxx b/slideshow/source/engine/animationnodes/basecontainernode.cxx
new file mode 100644
index 000000000000..8ee1c197fcb6
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/basecontainernode.cxx
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "basecontainernode.hxx"
+#include "tools.hxx"
+#include "nodetools.hxx"
+#include "delayevent.hxx"
+
+#include <boost/mem_fn.hpp>
+#include <algorithm>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+BaseContainerNode::BaseContainerNode(
+ const uno::Reference< animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : BaseNode( xNode, rParent, rContext ),
+ maChildren(),
+ mnFinishedChildren(0),
+ mbDurationIndefinite( isIndefiniteTiming( xNode->getEnd() ) &&
+ isIndefiniteTiming( xNode->getDuration() ) )
+{
+}
+
+void BaseContainerNode::dispose()
+{
+ forEachChildNode( boost::mem_fn(&Disposable::dispose) );
+ maChildren.clear();
+ BaseNode::dispose();
+}
+
+bool BaseContainerNode::init_st()
+{
+ mnFinishedChildren = 0;
+ // initialize all children
+ return (std::count_if(
+ maChildren.begin(), maChildren.end(),
+ boost::mem_fn(&AnimationNode::init) ) ==
+ static_cast<VectorOfNodes::difference_type>(maChildren.size()));
+}
+
+void BaseContainerNode::deactivate_st( NodeState eDestState )
+{
+ if (eDestState == FROZEN) {
+ // deactivate all children that are not FROZEN or ENDED:
+ forEachChildNode( boost::mem_fn(&AnimationNode::deactivate),
+ ~(FROZEN | ENDED) );
+ }
+ else {
+ // end all children that are not ENDED:
+ forEachChildNode( boost::mem_fn(&AnimationNode::end), ~ENDED );
+ }
+}
+
+bool BaseContainerNode::hasPendingAnimation() const
+{
+ // does any of our children returns "true" on
+ // AnimationNode::hasPendingAnimation()?
+ // If yes, we, too, return true
+ VectorOfNodes::const_iterator const iEnd( maChildren.end() );
+ return (std::find_if(
+ maChildren.begin(), iEnd,
+ boost::mem_fn(&AnimationNode::hasPendingAnimation) ) != iEnd);
+}
+
+void BaseContainerNode::appendChildNode( AnimationNodeSharedPtr const& pNode )
+{
+ if (! checkValidNode())
+ return;
+
+ // register derived classes as end listeners at all children.
+ // this is necessary to control the children animation
+ // sequence, and to determine our own end event
+ if (pNode->registerDeactivatingListener( getSelf() )) {
+ maChildren.push_back( pNode );
+ }
+}
+
+bool BaseContainerNode::isChildNode( AnimationNodeSharedPtr const& pNode ) const
+{
+ // find given notifier in child vector
+ VectorOfNodes::const_iterator const iBegin( maChildren.begin() );
+ VectorOfNodes::const_iterator const iEnd( maChildren.end() );
+ VectorOfNodes::const_iterator const iFind(
+ std::find( iBegin, iEnd, pNode ) );
+ return (iFind != iEnd);
+}
+
+bool BaseContainerNode::notifyDeactivatedChild(
+ AnimationNodeSharedPtr const& pChildNode )
+{
+ OSL_ASSERT( pChildNode->getState() == FROZEN ||
+ pChildNode->getState() == ENDED );
+ // early exit on invalid nodes
+ OSL_ASSERT( getState() != INVALID );
+ if( getState() == INVALID )
+ return false;
+
+ if (! isChildNode(pChildNode)) {
+ OSL_ENSURE( false, "unknown notifier!" );
+ return false;
+ }
+
+ std::size_t const nSize = maChildren.size();
+ OSL_ASSERT( mnFinishedChildren < nSize );
+ ++mnFinishedChildren;
+ bool const bFinished = (mnFinishedChildren >= nSize);
+
+ // all children finished, and we've got indefinite duration?
+ // think of ParallelTimeContainer::notifyDeactivating()
+ // if duration given, we will be deactivated by some end event
+ // @see fillCommonParameters()
+ if (bFinished && isDurationIndefinite()) {
+ deactivate();
+ }
+
+ return bFinished;
+}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+void BaseContainerNode::showState() const
+{
+ for( std::size_t i=0; i<maChildren.size(); ++i )
+ {
+ BaseNodeSharedPtr pNode =
+ boost::shared_dynamic_cast<BaseNode>(maChildren[i]);
+ VERBOSE_TRACE(
+ "Node connection: n0x%X -> n0x%X",
+ (const char*)this+debugGetCurrentOffset(),
+ (const char*)pNode.get()+debugGetCurrentOffset() );
+ pNode->showState();
+ }
+
+ BaseNode::showState();
+}
+#endif
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/basecontainernode.hxx b/slideshow/source/engine/animationnodes/basecontainernode.hxx
new file mode 100644
index 000000000000..3015694a2ec9
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/basecontainernode.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_BASECONTAINERNODE_HXX
+#define INCLUDED_SLIDESHOW_BASECONTAINERNODE_HXX
+
+#include "basenode.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** This interface extends BaseNode with child handling methods.
+ Used for XAnimationNode objects which have children
+*/
+class BaseContainerNode : public BaseNode
+{
+public:
+ BaseContainerNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext );
+
+ /** Add given child node to this container
+ */
+ void appendChildNode( AnimationNodeSharedPtr const& pNode );
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual void showState() const;
+ virtual const char* getDescription() const { return "BaseContainerNode"; }
+#endif
+
+protected:
+ // overrides from BaseNode
+ virtual void dispose();
+
+private:
+ virtual bool init_st();
+ virtual void deactivate_st( NodeState eDestState );
+ virtual bool hasPendingAnimation() const;
+ // force to be implemented by derived class:
+ virtual void activate_st() = 0;
+ virtual void notifyDeactivating(
+ AnimationNodeSharedPtr const& rNotifier ) = 0;
+
+protected:
+ bool isDurationIndefinite() const { return mbDurationIndefinite; }
+
+ bool isChildNode( AnimationNodeSharedPtr const& pNode ) const;
+
+ /// @return true: if all children have been deactivated
+ bool notifyDeactivatedChild( AnimationNodeSharedPtr const& pChildNode );
+
+ template <typename FuncT>
+ inline void forEachChildNode( FuncT const& func,
+ int nodeStateMask = -1 ) const
+ {
+ VectorOfNodes::const_iterator iPos( maChildren.begin() );
+ VectorOfNodes::const_iterator const iEnd( maChildren.end() );
+ for ( ; iPos != iEnd; ++iPos ) {
+ AnimationNodeSharedPtr const& pNode = *iPos;
+ if (nodeStateMask != -1 && (pNode->getState() & nodeStateMask) == 0)
+ continue;
+ func(pNode);
+ }
+ }
+
+ typedef ::std::vector<AnimationNodeSharedPtr> VectorOfNodes;
+ VectorOfNodes maChildren;
+ ::std::size_t mnFinishedChildren;
+
+private:
+ const bool mbDurationIndefinite;
+};
+
+typedef ::boost::shared_ptr< BaseContainerNode > BaseContainerNodeSharedPtr;
+
+} // namespace interface
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_BASECONTAINERNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/basenode.cxx b/slideshow/source/engine/animationnodes/basenode.cxx
new file mode 100644
index 000000000000..71450cb568a9
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/basenode.cxx
@@ -0,0 +1,771 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/animations/XAnimate.hpp>
+#include <com/sun/star/presentation/ParagraphTarget.hpp>
+#include <com/sun/star/animations/AnimationFill.hpp>
+#include <com/sun/star/animations/AnimationRestart.hpp>
+#include <com/sun/star/presentation/EffectNodeType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include "basenode.hxx"
+#include "eventmultiplexer.hxx"
+#include "basecontainernode.hxx"
+#include "eventqueue.hxx"
+#include "delayevent.hxx"
+#include "tools.hxx"
+#include "nodetools.hxx"
+#include "generateevent.hxx"
+#include "debug.hxx"
+
+#include <boost/bind.hpp>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+
+using namespace ::com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+typedef int StateTransitionTable[17];
+
+// State transition tables
+// =========================================================================
+
+const int* getStateTransitionTable( sal_Int16 nRestartMode,
+ sal_Int16 nFillMode )
+{
+ // TODO(F2): restart issues in below tables
+
+ // transition table for restart=NEVER, fill=REMOVE
+ static const StateTransitionTable stateTransitionTable_Never_Remove = {
+ AnimationNode::INVALID,
+ AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
+ AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
+ AnimationNode::INVALID,
+ AnimationNode::ENDED, // active successors for ACTIVE: no freeze here
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID, // active successors for FROZEN: this state is unreachable here
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED // active successors for ENDED: this state is a sink here (cannot restart)
+ };
+
+ // transition table for restart=WHEN_NOT_ACTIVE, fill=REMOVE
+ static const StateTransitionTable stateTransitionTable_NotActive_Remove = {
+ AnimationNode::INVALID,
+ AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
+ AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
+ AnimationNode::INVALID,
+ AnimationNode::ENDED, // active successors for ACTIVE: no freeze here
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID, // active successors for FROZEN:
+ // this state is unreachable here
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE // active successors for ENDED:
+ // restart possible when ended
+ };
+
+ // transition table for restart=ALWAYS, fill=REMOVE
+ static const StateTransitionTable stateTransitionTable_Always_Remove = {
+ AnimationNode::INVALID,
+ AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
+ AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED, // active successors for ACTIVE: restart
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID, // active successors for FROZEN:
+ // this state is unreachable here
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED // active successors for ENDED: restart
+ };
+
+ // transition table for restart=NEVER, fill=FREEZE
+ static const StateTransitionTable stateTransitionTable_Never_Freeze = {
+ AnimationNode::INVALID,
+ AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
+ AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
+ AnimationNode::INVALID,
+ AnimationNode::FROZEN|AnimationNode::ENDED, // active successors for ACTIVE: freeze object
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED, // active successors for FROZEN: end
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED, // active successors for ENDED: this state is a sink here (cannot restart)
+ };
+
+ // transition table for restart=WHEN_NOT_ACTIVE, fill=FREEZE
+ static const StateTransitionTable stateTransitionTable_NotActive_Freeze = {
+ AnimationNode::INVALID,
+ AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
+ AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
+ AnimationNode::INVALID,
+ AnimationNode::FROZEN|AnimationNode::ENDED, // active successors for ACTIVE: freeze object
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE, // active successors for FROZEN:
+ // restart possible when ended
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE // active successors for ENDED:
+ // restart possible when ended
+ };
+
+ // transition table for restart=ALWAYS, fill=FREEZE
+ static const StateTransitionTable stateTransitionTable_Always_Freeze = {
+ AnimationNode::INVALID,
+ AnimationNode::RESOLVED|AnimationNode::ENDED, // active successors for UNRESOLVED
+ AnimationNode::ACTIVE|AnimationNode::ENDED, // active successors for RESOLVED
+ AnimationNode::INVALID,
+ AnimationNode::FROZEN|AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED, // active successors for ACTIVE:
+ // end object, restart
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::RESOLVED|AnimationNode::ACTIVE, // active successors for FROZEN: restart possible
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::INVALID,
+ AnimationNode::ENDED|AnimationNode::ACTIVE|AnimationNode::RESOLVED // active successors for ENDED: restart
+ };
+
+ static const StateTransitionTable* tableGuide[] = {
+ &stateTransitionTable_Never_Remove,
+ &stateTransitionTable_NotActive_Remove,
+ &stateTransitionTable_Always_Remove,
+ &stateTransitionTable_Never_Freeze,
+ &stateTransitionTable_NotActive_Freeze,
+ &stateTransitionTable_Always_Freeze
+ };
+
+ int nRestartValue;
+ switch( nRestartMode ) {
+ default:
+ case animations::AnimationRestart::DEFAULT:
+ // same value: animations::AnimationRestart::INHERIT:
+ OSL_ENSURE(
+ false, "getStateTransitionTable(): unexpected case for restart" );
+ // FALLTHROUGH intended
+ case animations::AnimationRestart::NEVER:
+ nRestartValue = 0;
+ break;
+ case animations::AnimationRestart::WHEN_NOT_ACTIVE:
+ nRestartValue = 1;
+ break;
+ case animations::AnimationRestart::ALWAYS:
+ nRestartValue = 2;
+ break;
+ }
+
+ int nFillValue;
+ switch( nFillMode ) {
+ default:
+ case animations::AnimationFill::AUTO:
+ case animations::AnimationFill::DEFAULT:
+ // same value: animations::AnimationFill::INHERIT:
+ OSL_ENSURE(
+ false, "getStateTransitionTable(): unexpected case for fill" );
+ // FALLTHROUGH intended
+ case animations::AnimationFill::REMOVE:
+ nFillValue = 0;
+ break;
+ case animations::AnimationFill::FREEZE:
+ case animations::AnimationFill::HOLD:
+ case animations::AnimationFill::TRANSITION:
+ nFillValue = 1;
+ break;
+ }
+
+ return *tableGuide[ 3*nFillValue + nRestartValue ];
+}
+
+/// Little helper predicate, to detect main sequence root node
+bool isMainSequenceRootNode_(
+ const uno::Reference< animations::XAnimationNode >& xNode )
+{
+ // detect main sequence root node (need that for
+ // end-of-mainsequence signalling below)
+ beans::NamedValue const aSearchKey(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ),
+ uno::makeAny( presentation::EffectNodeType::MAIN_SEQUENCE ) );
+
+ uno::Sequence<beans::NamedValue> const userData(xNode->getUserData());
+ return findNamedValue( userData, aSearchKey );
+}
+
+} // anon namespace
+
+// BaseNode implementation
+//=========================================================================
+
+/** state transition handling
+ */
+class BaseNode::StateTransition : private boost::noncopyable
+{
+public:
+ enum Options { NONE, FORCE };
+
+ explicit StateTransition( BaseNode * pNode )
+ : mpNode(pNode), meToState(INVALID) {}
+
+ ~StateTransition() {
+ clear();
+ }
+
+ bool enter( NodeState eToState, int options = NONE )
+ {
+ OSL_ENSURE( meToState == INVALID,
+ "### commit() before enter()ing again!" );
+ if (meToState != INVALID)
+ return false;
+ bool const bForce = ((options & FORCE) != 0);
+ if (!bForce && !mpNode->isTransition( mpNode->meCurrState, eToState ))
+ return false;
+ // recursion detection:
+ if ((mpNode->meCurrentStateTransition & eToState) != 0)
+ return false; // already in wanted transition
+ // mark transition:
+ mpNode->meCurrentStateTransition |= eToState;
+ meToState = eToState;
+ return true; // in transition
+ }
+
+ void commit() {
+ OSL_ENSURE( meToState != INVALID, "### nothing to commit!" );
+ if (meToState != INVALID) {
+ mpNode->meCurrState = meToState;
+ clear();
+ }
+
+ // Uncomment the following line to write the node tree to file on
+ // every state change of one of its nodes.
+ // Debug_ShowNodeTree(mpNode->mpSelf);
+ }
+
+ void clear() {
+ if (meToState != INVALID) {
+ OSL_ASSERT( (mpNode->meCurrentStateTransition & meToState) != 0 );
+ mpNode->meCurrentStateTransition &= ~meToState;
+ meToState = INVALID;
+ }
+ }
+
+private:
+ BaseNode *const mpNode;
+ NodeState meToState;
+};
+
+BaseNode::BaseNode( const uno::Reference< animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext ) :
+ maContext( rContext.maContext ),
+ maDeactivatingListeners(),
+ mxAnimationNode( xNode ),
+ mpParent( rParent ),
+ mpSelf(),
+ mpStateTransitionTable( NULL ),
+ mnStartDelay( rContext.mnStartDelay ),
+ meCurrState( UNRESOLVED ),
+ meCurrentStateTransition( 0 ),
+ mpCurrentEvent(),
+ mbIsMainSequenceRootNode( isMainSequenceRootNode_( xNode ) )
+{
+ ENSURE_OR_THROW( mxAnimationNode.is(),
+ "BaseNode::BaseNode(): Invalid XAnimationNode" );
+
+ // setup state transition table
+ mpStateTransitionTable = getStateTransitionTable( getRestartMode(),
+ getFillMode() );
+}
+
+void BaseNode::dispose()
+{
+ meCurrState = INVALID;
+
+ // discharge a loaded event, if any:
+ if (mpCurrentEvent) {
+ mpCurrentEvent->dispose();
+ mpCurrentEvent.reset();
+ }
+ maDeactivatingListeners.clear();
+ mxAnimationNode.clear();
+ mpParent.reset();
+ mpSelf.reset();
+ maContext.dispose();
+}
+
+
+sal_Int16 BaseNode::getRestartMode()
+{
+ const sal_Int16 nTmp( mxAnimationNode->getRestart() );
+ return (nTmp != animations::AnimationRestart::DEFAULT &&
+ nTmp != animations::AnimationRestart::INHERIT)
+ ? nTmp : getRestartDefaultMode();
+}
+
+sal_Int16 BaseNode::getFillMode()
+{
+ const sal_Int16 nTmp( mxAnimationNode->getFill() );
+ const sal_Int16 nFill((nTmp != animations::AnimationFill::DEFAULT &&
+ nTmp != animations::AnimationFill::INHERIT)
+ ? nTmp : getFillDefaultMode());
+
+ // For AUTO fill mode, SMIL specifies that fill mode is FREEZE,
+ // if no explicit active duration is given
+ // (no duration, end, repeatCount or repeatDuration given),
+ // and REMOVE otherwise
+ if( nFill == animations::AnimationFill::AUTO ) {
+ return (isIndefiniteTiming( mxAnimationNode->getDuration() ) &&
+ isIndefiniteTiming( mxAnimationNode->getEnd() ) &&
+ !mxAnimationNode->getRepeatCount().hasValue() &&
+ isIndefiniteTiming( mxAnimationNode->getRepeatDuration() ))
+ ? animations::AnimationFill::FREEZE
+ : animations::AnimationFill::REMOVE;
+ }
+ else {
+ return nFill;
+ }
+}
+
+sal_Int16 BaseNode::getFillDefaultMode() const
+{
+ sal_Int16 nFillDefault = mxAnimationNode->getFillDefault();
+ if (nFillDefault == animations::AnimationFill::DEFAULT) {
+ nFillDefault = (mpParent != 0
+ ? mpParent->getFillDefaultMode()
+ : animations::AnimationFill::AUTO);
+ }
+ return nFillDefault;
+}
+
+sal_Int16 BaseNode::getRestartDefaultMode() const
+{
+ sal_Int16 nRestartDefaultMode = mxAnimationNode->getRestartDefault();
+ if (nRestartDefaultMode == animations::AnimationRestart::DEFAULT) {
+ nRestartDefaultMode = (mpParent != 0
+ ? mpParent->getRestartDefaultMode()
+ : animations::AnimationRestart::ALWAYS);
+ }
+ return nRestartDefaultMode;
+}
+
+uno::Reference<animations::XAnimationNode> BaseNode::getXAnimationNode() const
+{
+ return mxAnimationNode;
+}
+
+bool BaseNode::init()
+{
+ if (! checkValidNode())
+ return false;
+ meCurrState = UNRESOLVED;
+ // discharge a loaded event, if any:
+ if (mpCurrentEvent) {
+ mpCurrentEvent->dispose();
+ mpCurrentEvent.reset();
+ }
+ return init_st(); // may call derived class
+}
+
+bool BaseNode::init_st()
+{
+ return true;
+}
+
+bool BaseNode::resolve()
+{
+ if (! checkValidNode())
+ return false;
+
+ OSL_ASSERT( meCurrState != RESOLVED );
+ if (inStateOrTransition( RESOLVED ))
+ return true;
+
+ StateTransition st(this);
+ if (st.enter( RESOLVED ) &&
+ isTransition( RESOLVED, ACTIVE ) &&
+ resolve_st() /* may call derived class */)
+ {
+ st.commit(); // changing state
+
+ // discharge a loaded event, if any:
+ if (mpCurrentEvent)
+ mpCurrentEvent->dispose();
+
+ // schedule activation event:
+
+ // This method takes the NodeContext::mnStartDelay value into account,
+ // to cater for iterate container time shifts. We cannot put different
+ // iterations of the iterate container's children into different
+ // subcontainer (such as a 'DelayContainer', which delays resolving its
+ // children by a fixed amount), since all iterations' nodes must be
+ // resolved at the same time (otherwise, the delayed subset creation
+ // will not work, i.e. deactivate the subsets too late in the master
+ // shape).
+ uno::Any const aBegin( mxAnimationNode->getBegin() );
+ if (aBegin.hasValue()) {
+ mpCurrentEvent = generateEvent(
+ aBegin, boost::bind( &AnimationNode::activate, mpSelf ),
+ maContext, mnStartDelay );
+ }
+ else {
+ // For some leaf nodes, PPT import yields empty begin time,
+ // although semantically, it should be 0.0
+ // TODO(F3): That should really be provided by the PPT import
+
+ // schedule delayed activation event. Take iterate node
+ // timeout into account
+ mpCurrentEvent = makeDelay(
+ boost::bind( &AnimationNode::activate, mpSelf ),
+ mnStartDelay,
+ "AnimationNode::activate with delay");
+ maContext.mrEventQueue.addEvent( mpCurrentEvent );
+ }
+
+ return true;
+ }
+ return false;
+}
+
+bool BaseNode::resolve_st()
+{
+ return true;
+}
+
+
+bool BaseNode::activate()
+{
+ if (! checkValidNode())
+ return false;
+
+ OSL_ASSERT( meCurrState != ACTIVE );
+ if (inStateOrTransition( ACTIVE ))
+ return true;
+
+ StateTransition st(this);
+ if (st.enter( ACTIVE )) {
+
+ activate_st(); // calling derived class
+
+ st.commit(); // changing state
+
+ maContext.mrEventMultiplexer.notifyAnimationStart( mpSelf );
+
+ return true;
+ }
+
+ return false;
+}
+
+void BaseNode::activate_st()
+{
+ scheduleDeactivationEvent();
+}
+
+void BaseNode::scheduleDeactivationEvent( EventSharedPtr const& pEvent )
+{
+ if (mpCurrentEvent) {
+ mpCurrentEvent->dispose();
+ mpCurrentEvent.reset();
+ }
+ if (pEvent) {
+ if (maContext.mrEventQueue.addEvent( pEvent ))
+ mpCurrentEvent = pEvent;
+ }
+ else {
+ // This method need not take the
+ // NodeContext::mnStartDelay value into account,
+ // because the deactivation event is only scheduled
+ // when the effect is started: the timeout is then
+ // already respected.
+
+ // xxx todo:
+ // think about set node, anim base node!
+ // if anim base node has no activity, this is called to schedule deactivatiion,
+ // but what if it does not schedule anything?
+
+ // TODO(F2): Handle end time attribute, too
+ mpCurrentEvent = generateEvent(
+ mxAnimationNode->getDuration(),
+ boost::bind( &AnimationNode::deactivate, mpSelf ),
+ maContext, 0.0 );
+ }
+}
+
+void BaseNode::deactivate()
+{
+ if (inStateOrTransition( ENDED | FROZEN ) || !checkValidNode())
+ return;
+
+ if (isTransition( meCurrState, FROZEN, false /* no OSL_ASSERT */ )) {
+ // do transition to FROZEN:
+ StateTransition st(this);
+ if (st.enter( FROZEN, StateTransition::FORCE )) {
+
+ deactivate_st( FROZEN );
+ st.commit();
+
+ notifyEndListeners();
+
+ // discharge a loaded event, before going on:
+ if (mpCurrentEvent) {
+ mpCurrentEvent->dispose();
+ mpCurrentEvent.reset();
+ }
+ }
+ }
+ else {
+ // use end instead:
+ end();
+ }
+ // state has changed either to FROZEN or ENDED
+}
+
+void BaseNode::deactivate_st( NodeState )
+{
+}
+
+void BaseNode::end()
+{
+ bool const bIsFrozenOrInTransitionToFrozen = inStateOrTransition( FROZEN );
+ if (inStateOrTransition( ENDED ) || !checkValidNode())
+ return;
+
+ // END must always be reachable. If not, that's an error in the
+ // transition tables
+ OSL_ENSURE( isTransition( meCurrState, ENDED ),
+ "end state not reachable in transition table" );
+
+ StateTransition st(this);
+ if (st.enter( ENDED, StateTransition::FORCE )) {
+
+ deactivate_st( ENDED );
+ st.commit(); // changing state
+
+ // if is FROZEN or is to be FROZEN, then
+ // will/already notified deactivating listeners
+ if (!bIsFrozenOrInTransitionToFrozen)
+ notifyEndListeners();
+
+ // discharge a loaded event, before going on:
+ if (mpCurrentEvent) {
+ mpCurrentEvent->dispose();
+ mpCurrentEvent.reset();
+ }
+ }
+}
+
+void BaseNode::notifyDeactivating( const AnimationNodeSharedPtr& rNotifier )
+{
+ (void) rNotifier; // avoid warning
+ OSL_ASSERT( rNotifier->getState() == FROZEN ||
+ rNotifier->getState() == ENDED );
+ // TODO(F1): for end sync functionality, this might indeed be used some day
+}
+
+void BaseNode::notifyEndListeners() const
+{
+ // notify all listeners
+ std::for_each( maDeactivatingListeners.begin(),
+ maDeactivatingListeners.end(),
+ boost::bind( &AnimationNode::notifyDeactivating, _1,
+ boost::cref(mpSelf) ) );
+
+ // notify state change
+ maContext.mrEventMultiplexer.notifyAnimationEnd( mpSelf );
+
+ // notify main sequence end (iff we're the main
+ // sequence root node). This is because the main
+ // sequence determines the active duration of the
+ // slide. All other sequences are secondary, in that
+ // they don't prevent a slide change from happening,
+ // even if they have not been completed. In other
+ // words, all sequences except the main sequence are
+ // optional for the slide lifetime.
+ if (isMainSequenceRootNode())
+ maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
+}
+
+AnimationNode::NodeState BaseNode::getState() const
+{
+ return meCurrState;
+}
+
+bool BaseNode::registerDeactivatingListener(
+ const AnimationNodeSharedPtr& rNotifee )
+{
+ if (! checkValidNode())
+ return false;
+
+ ENSURE_OR_RETURN_FALSE(
+ rNotifee,
+ "BaseNode::registerDeactivatingListener(): invalid notifee" );
+ maDeactivatingListeners.push_back( rNotifee );
+
+ return true;
+}
+
+void BaseNode::setSelf( const BaseNodeSharedPtr& rSelf )
+{
+ ENSURE_OR_THROW( rSelf.get() == this,
+ "BaseNode::setSelf(): got ptr to different object" );
+ ENSURE_OR_THROW( !mpSelf,
+ "BaseNode::setSelf(): called multiple times" );
+
+ mpSelf = rSelf;
+}
+
+// Debug
+//=========================================================================
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+void BaseNode::showState() const
+{
+ const AnimationNode::NodeState eNodeState( getState() );
+
+ if( eNodeState == AnimationNode::INVALID )
+ VERBOSE_TRACE( "Node state: n0x%X [label=\"%s\",style=filled,"
+ "fillcolor=\"0.5,0.2,0.5\"]",
+ (const char*)this+debugGetCurrentOffset(),
+ getDescription() );
+ else
+ VERBOSE_TRACE( "Node state: n0x%X [label=\"%s\",style=filled,"
+ "fillcolor=\"%f,1.0,1.0\"]",
+ (const char*)this+debugGetCurrentOffset(),
+ getDescription(),
+ log(double(getState()))/4.0 );
+
+ // determine additional node information
+ uno::Reference<animations::XAnimate> const xAnimate( mxAnimationNode,
+ uno::UNO_QUERY );
+ if( xAnimate.is() )
+ {
+ uno::Reference< drawing::XShape > xTargetShape( xAnimate->getTarget(),
+ uno::UNO_QUERY );
+
+ if( !xTargetShape.is() )
+ {
+ ::com::sun::star::presentation::ParagraphTarget aTarget;
+
+ // no shape provided. Maybe a ParagraphTarget?
+ if( (xAnimate->getTarget() >>= aTarget) )
+ xTargetShape = aTarget.Shape;
+ }
+
+ if( xTargetShape.is() )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xTargetShape,
+ uno::UNO_QUERY );
+
+ // read shape name
+ ::rtl::OUString aName;
+ if( (xPropSet->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Name") ) )
+ >>= aName) )
+ {
+ const ::rtl::OString& rAsciiName(
+ ::rtl::OUStringToOString( aName,
+ RTL_TEXTENCODING_ASCII_US ) );
+
+ VERBOSE_TRACE( "Node info: n0x%X, name \"%s\"",
+ (const char*)this+debugGetCurrentOffset(),
+ rAsciiName.getStr() );
+ }
+ }
+ }
+}
+
+const char* BaseNode::getDescription() const
+{
+ return "BaseNode";
+}
+
+void BaseNode::showTreeFromWithin() const
+{
+ // find root node
+ BaseNodeSharedPtr pCurrNode( mpSelf );
+ while( pCurrNode->mpParent ) pCurrNode = pCurrNode->mpParent;
+
+ pCurrNode->showState();
+}
+#endif
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/basenode.hxx b/slideshow/source/engine/animationnodes/basenode.hxx
new file mode 100644
index 000000000000..f927c1be8f89
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/basenode.hxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_BASENODE_HXX
+#define INCLUDED_SLIDESHOW_BASENODE_HXX
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <osl/diagnose.hxx>
+
+#include "event.hxx"
+#include "animationnode.hxx"
+#include "slideshowcontext.hxx"
+#include "shapesubset.hxx"
+
+#include <boost/noncopyable.hpp>
+#include <vector>
+
+namespace slideshow {
+namespace internal {
+
+/** Context for every node.
+
+ Besides the global AnimationNodeFactory::Context data,
+ this struct also contains the current DocTree subset
+ for this node. If start and end index of the
+ DocTreeNode are equal, the node should use the
+ complete shape.
+*/
+struct NodeContext
+{
+ NodeContext( const SlideShowContext& rContext,
+ const ::basegfx::B2DVector& rSlideSize )
+ : maContext( rContext ),
+ maSlideSize( rSlideSize ),
+ mpMasterShapeSubset(),
+ mnStartDelay(0.0),
+ mbIsIndependentSubset( true )
+ {}
+
+ void dispose()
+ {
+ maContext.dispose();
+ mpMasterShapeSubset.reset();
+ }
+
+ /// Context as passed to createAnimationNode()
+ SlideShowContext maContext;
+
+ /// Size in user coordinate space of the corresponding slide
+ ::basegfx::B2DVector maSlideSize;
+
+ /// Shape to be used (provided by parent, e.g. for iterations)
+ ShapeSubsetSharedPtr mpMasterShapeSubset;
+
+ /// Additional delay to node begin (to offset iterate effects)
+ double mnStartDelay;
+
+ /// When true, subset must be created during slide initialization
+ bool mbIsIndependentSubset;
+};
+
+class BaseContainerNode;
+
+/** This interface extends AnimationNode with some
+ file-private accessor methods.
+*/
+class BaseNode : public AnimationNode,
+ protected ::osl::DebugBase<BaseNode>,
+ private ::boost::noncopyable
+{
+public:
+ BaseNode( ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext );
+
+ /** Provide the node with a shared_ptr to itself.
+
+ Since implementation has to create objects which need
+ a shared_ptr to this node, and a pointee cannot
+ retrieve a shared_ptr to itself internally, have to
+ set that from the outside.
+ */
+ void setSelf( const ::boost::shared_ptr< BaseNode >& rSelf );
+
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual void showState() const;
+ virtual const char* getDescription() const;
+ void showTreeFromWithin() const;
+#endif
+
+ const ::boost::shared_ptr< BaseContainerNode >& getParentNode() const
+ { return mpParent; }
+
+ // Disposable:
+ virtual void dispose();
+
+ // AnimationNode:
+ virtual bool init();
+ virtual bool resolve();
+ virtual bool activate();
+ virtual void deactivate();
+ virtual void end();
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> getXAnimationNode() const;
+ virtual NodeState getState() const;
+ virtual bool registerDeactivatingListener(
+ const AnimationNodeSharedPtr& rNotifee );
+ // nop:
+ virtual void notifyDeactivating( const AnimationNodeSharedPtr& rNotifier );
+
+ bool isMainSequenceRootNode() const { return mbIsMainSequenceRootNode; }
+
+protected:
+ void scheduleDeactivationEvent( EventSharedPtr const& pEvent =
+ EventSharedPtr() );
+
+ SlideShowContext const& getContext() const { return maContext; }
+ ::boost::shared_ptr<BaseNode> const& getSelf() const { return mpSelf; }
+
+ bool checkValidNode() const {
+ ENSURE_OR_THROW( mpSelf, "no self ptr set!" );
+ bool const bRet = (meCurrState != INVALID);
+ OSL_ENSURE( bRet, "### INVALID node!" );
+ return bRet;
+ }
+
+private:
+ // all state affecting methods have "_st" counterparts being called at
+ // derived classes when in state transistion: no-ops here at BaseNode...
+ virtual bool init_st();
+ virtual bool resolve_st();
+ virtual void activate_st();
+ virtual void deactivate_st( NodeState eDestState );
+
+private:
+ /// notifies
+ /// - all registered deactivation listeners
+ /// - single animation end (every node)
+ /// - slide animations (if main sequence root node)
+ void notifyEndListeners() const;
+
+ /// Get the node's restart mode
+ sal_Int16 getRestartMode();
+
+ /** Get the default restart mode
+
+ If this node's default mode is
+ AnimationRestart::DEFAULT, this method recursively
+ calls the parent node.
+ */
+ sal_Int16 getRestartDefaultMode() const;
+
+ /// Get the node's fill mode
+ sal_Int16 getFillMode();
+
+ /** Get the default fill mode.
+
+ If this node's default mode is AnimationFill::DEFAULT,
+ this method recursively calls the parent node.
+ */
+ sal_Int16 getFillDefaultMode() const;
+
+ bool isTransition( NodeState eFromState, NodeState eToState,
+ bool debugAssert = true ) const {
+ (void) debugAssert; // avoid warning
+ bool const bRet =((mpStateTransitionTable[eFromState] & eToState) != 0);
+ OSL_ENSURE( !debugAssert || bRet, "### state unreachable!" );
+ return bRet;
+ }
+
+ bool inStateOrTransition( int mask ) const {
+ return ((meCurrState & mask) != 0 ||
+ (meCurrentStateTransition & mask) != 0);
+ }
+
+ class StateTransition;
+ friend class StateTransition;
+
+private:
+ SlideShowContext maContext;
+
+ typedef ::std::vector< AnimationNodeSharedPtr > ListenerVector;
+
+ ListenerVector maDeactivatingListeners;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode > mxAnimationNode;
+ ::boost::shared_ptr< BaseContainerNode > mpParent;
+ ::boost::shared_ptr< BaseNode > mpSelf;
+ const int* mpStateTransitionTable;
+ const double mnStartDelay;
+ NodeState meCurrState;
+ int meCurrentStateTransition;
+ EventSharedPtr mpCurrentEvent;
+ const bool mbIsMainSequenceRootNode;
+};
+
+typedef ::boost::shared_ptr< BaseNode > BaseNodeSharedPtr;
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_BASENODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/generateevent.cxx b/slideshow/source/engine/animationnodes/generateevent.cxx
new file mode 100644
index 000000000000..40380b080ac3
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/generateevent.cxx
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/animations/XAnimationNode.hpp>
+#include <com/sun/star/animations/Timing.hpp>
+#include <com/sun/star/animations/EventTrigger.hpp>
+#include <com/sun/star/animations/Event.hpp>
+
+#include "shape.hxx"
+#include "subsettableshapemanager.hxx"
+#include "usereventqueue.hxx"
+#include "slideshowcontext.hxx"
+#include "delayevent.hxx"
+
+namespace slideshow {
+namespace internal {
+
+using namespace com::sun::star;
+
+EventSharedPtr generateEvent(
+ uno::Any const& rEventDescription,
+ Delay::FunctorT const& rFunctor,
+ SlideShowContext const& rContext,
+ double nAdditionalDelay )
+{
+ EventSharedPtr pEvent;
+
+ if (! rEventDescription.hasValue())
+ return pEvent;
+
+ animations::Timing eTiming;
+ animations::Event aEvent;
+ uno::Sequence<uno::Any> aSequence;
+ double nDelay1 = 0;
+
+ if (rEventDescription >>= eTiming) {
+ switch (eTiming) {
+ case animations::Timing_INDEFINITE:
+ break; // don't schedule no event
+ case animations::Timing_MEDIA:
+ OSL_ENSURE( false, "MEDIA timing not yet implemented!" );
+ break;
+ default:
+ ENSURE_OR_THROW( false, "unexpected case!" );
+ }
+ }
+ else if (rEventDescription >>= aEvent) {
+
+ // try to extract additional event delay
+ double nDelay2 = 0.0;
+ if (aEvent.Offset.hasValue() && !(aEvent.Offset >>= nDelay2)) {
+ OSL_ENSURE( false, "offset values apart from DOUBLE not "
+ "recognized in animations::Event!" );
+ }
+
+ // common vars used inside switch
+ uno::Reference<animations::XAnimationNode> xNode;
+ uno::Reference<drawing::XShape> xShape;
+ ShapeSharedPtr pShape;
+
+ // TODO(F1): Respect aEvent.Repeat value
+
+ switch (aEvent.Trigger) {
+ default:
+ ENSURE_OR_THROW( false, "unexpected event trigger!" );
+ case animations::EventTrigger::NONE:
+ // no event at all
+ break;
+ case animations::EventTrigger::ON_BEGIN:
+ OSL_ENSURE( false, "event trigger ON_BEGIN not yet implemented!" );
+ break;
+ case animations::EventTrigger::ON_END:
+ OSL_ENSURE( false, "event trigger ON_END not yet implemented!" );
+ break;
+ case animations::EventTrigger::BEGIN_EVENT:
+ // try to extract XAnimationNode event source
+ if (aEvent.Source >>= xNode) {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, BEGIN_EVENT");
+ rContext.mrUserEventQueue.registerAnimationStartEvent(
+ pEvent, xNode );
+ }
+ else {
+ OSL_ENSURE(false, "could not extract source XAnimationNode "
+ "for BEGIN_EVENT!" );
+ }
+ break;
+ case animations::EventTrigger::END_EVENT:
+ // try to extract XAnimationNode event source
+ if (aEvent.Source >>= xNode) {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, END_EVENT");
+ rContext.mrUserEventQueue.registerAnimationEndEvent(
+ pEvent, xNode );
+ }
+ else {
+ OSL_ENSURE( false, "could not extract source XAnimationNode "
+ "for END_EVENT!" );
+ }
+ break;
+ case animations::EventTrigger::ON_CLICK:
+ // try to extract XShape event source
+ if ((aEvent.Source >>= xShape) &&
+ (pShape = rContext.mpSubsettableShapeManager->lookupShape(xShape)).get())
+ {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, ON_CLICK");
+ rContext.mrUserEventQueue.registerShapeClickEvent(
+ pEvent, pShape );
+ }
+ else {
+ OSL_ENSURE( false, "could not extract source XAnimationNode "
+ "for ON_CLICK!" );
+ }
+ break;
+ case animations::EventTrigger::ON_DBL_CLICK:
+ // try to extract XShape event source
+ if ((aEvent.Source >>= xShape) &&
+ (pShape = rContext.mpSubsettableShapeManager->lookupShape(xShape)).get())
+ {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, ON_DBL_CLICK");
+ rContext.mrUserEventQueue.registerShapeDoubleClickEvent(
+ pEvent, pShape );
+ }
+ else {
+ OSL_ENSURE( false, "could not extract source XAnimationNode "
+ "for ON_DBL_CLICK!" );
+ }
+ break;
+ case animations::EventTrigger::ON_MOUSE_ENTER:
+ // try to extract XShape event source
+ if ((aEvent.Source >>= xShape) &&
+ (pShape = rContext.mpSubsettableShapeManager->lookupShape(xShape)).get())
+ {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, ON_MOUSE_ENTER");
+ rContext.mrUserEventQueue.registerMouseEnterEvent(
+ pEvent, pShape );
+ }
+ else {
+ OSL_ENSURE( false, "could not extract source XAnimationNode "
+ "for ON_MOUSE_ENTER!" );
+ }
+ break;
+ case animations::EventTrigger::ON_MOUSE_LEAVE:
+ // try to extract XShape event source
+ if ((aEvent.Source >>= xShape) &&
+ (pShape = rContext.mpSubsettableShapeManager->lookupShape(xShape)).get())
+ {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, ON_MOUSE_LEAVE");
+ rContext.mrUserEventQueue.registerMouseLeaveEvent(
+ pEvent, pShape );
+ }
+ else {
+ OSL_ENSURE( false, "could not extract source XAnimationNode "
+ "for ON_MOUSE_LEAVE!" );
+ }
+ break;
+ case animations::EventTrigger::ON_PREV:
+ OSL_ENSURE( false, "event trigger ON_PREV not yet implemented, "
+ "mapped to ON_NEXT!" );
+ // FALLTHROUGH intended
+ case animations::EventTrigger::ON_NEXT:
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, ON_NEXT");
+ rContext.mrUserEventQueue.registerNextEffectEvent( pEvent );
+ break;
+ case animations::EventTrigger::ON_STOP_AUDIO:
+ // try to extract XAnimationNode event source
+ if (aEvent.Source >>= xNode) {
+ pEvent = makeDelay( rFunctor,
+ nDelay2 + nAdditionalDelay,
+ "generateEvent, ON_STOP_AUDIO");
+ rContext.mrUserEventQueue.registerAudioStoppedEvent(
+ pEvent, xNode );
+ }
+ else {
+ OSL_ENSURE( false, "could not extract source XAnimationNode "
+ "for ON_STOP_AUDIO!" );
+ }
+ break;
+ case animations::EventTrigger::REPEAT:
+ OSL_ENSURE( false, "event trigger REPEAT not yet implemented!" );
+ break;
+ }
+ }
+ else if (rEventDescription >>= aSequence) {
+ OSL_ENSURE( false, "sequence of timing primitives "
+ "not yet implemented!" );
+ }
+ else if (rEventDescription >>= nDelay1) {
+ pEvent = makeDelay( rFunctor,
+ nDelay1 + nAdditionalDelay,
+ "generateEvent with delay");
+ // schedule delay event
+ rContext.mrEventQueue.addEvent( pEvent );
+ }
+
+ return pEvent;
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/generateevent.hxx b/slideshow/source/engine/animationnodes/generateevent.hxx
new file mode 100644
index 000000000000..fcadee19dfd2
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/generateevent.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_GENERATEEVENT_HXX
+#define INCLUDED_SLIDESHOW_GENERATEEVENT_HXX
+
+#include "slideshowcontext.hxx"
+#include "delayevent.hxx"
+#include "com/sun/star/uno/Any.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** Create an event for the given description, calling the given functor.
+
+ @param rEventDescription
+ Directly from API
+
+ @param rFunctor
+ Functor to call when event fires.
+
+ @param rContext
+ Context struct, to provide event queue
+
+ @param nAdditionalDelay
+ Additional delay, gets added on top of timeout.
+*/
+EventSharedPtr generateEvent(
+ ::com::sun::star::uno::Any const& rEventDescription,
+ Delay::FunctorT const& rFunctor,
+ SlideShowContext const& rContext,
+ double nAdditionalDelay );
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_GENERATEEVENT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/makefile.mk b/slideshow/source/engine/animationnodes/makefile.mk
new file mode 100644
index 000000000000..fc1c80352703
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/makefile.mk
@@ -0,0 +1,61 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=slideshow
+TARGET=animationnodes
+ENABLE_EXCEPTIONS=TRUE
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Common ----------------------------------------------------------
+
+SLOFILES = $(SLO)$/animationaudionode.obj \
+ $(SLO)$/animationcommandnode.obj \
+ $(SLO)$/animationbasenode.obj \
+ $(SLO)$/animationcolornode.obj \
+ $(SLO)$/animationnodefactory.obj \
+ $(SLO)$/animationpathmotionnode.obj \
+ $(SLO)$/animationsetnode.obj \
+ $(SLO)$/animationtransformnode.obj \
+ $(SLO)$/animationtransitionfilternode.obj \
+ $(SLO)$/basecontainernode.obj \
+ $(SLO)$/basenode.obj \
+ $(SLO)$/nodetools.obj \
+ $(SLO)$/paralleltimecontainer.obj \
+ $(SLO)$/propertyanimationnode.obj \
+ $(SLO)$/sequentialtimecontainer.obj \
+ $(SLO)$/generateevent.obj
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/animationnodes/nodetools.cxx b/slideshow/source/engine/animationnodes/nodetools.cxx
new file mode 100644
index 000000000000..ce7fab6d3506
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/nodetools.cxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <com/sun/star/animations/Timing.hpp>
+
+#include <tools.hxx>
+#include <nodetools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ int& debugGetCurrentOffset()
+ {
+ static int lcl_nOffset = 0; // to make each tree output distinct
+
+ return lcl_nOffset;
+ }
+
+ void debugNodesShowTree( const BaseNode* pNode )
+ {
+ if( pNode )
+ pNode->showState();
+
+ ++debugGetCurrentOffset();
+ }
+
+ void debugNodesShowTreeWithin( const BaseNode* pNode )
+ {
+ if( pNode )
+ pNode->showTreeFromWithin();
+
+ ++debugGetCurrentOffset();
+ }
+#endif
+
+ AttributableShapeSharedPtr lookupAttributableShape( const ShapeManagerSharedPtr& rShapeManager,
+ const uno::Reference< drawing::XShape >& xShape )
+ {
+ ENSURE_OR_THROW( rShapeManager,
+ "lookupAttributableShape(): invalid ShapeManager" );
+
+ ShapeSharedPtr pShape( rShapeManager->lookupShape( xShape ) );
+
+ ENSURE_OR_THROW( pShape,
+ "lookupAttributableShape(): no shape found for given XShape" );
+
+ AttributableShapeSharedPtr pRes(
+ ::boost::dynamic_pointer_cast< AttributableShape >( pShape ) );
+
+ // TODO(E3): Cannot throw here, people might set animation info
+ // for non-animatable shapes from the API. AnimationNodes must catch
+ // the exception and handle that differently
+ ENSURE_OR_THROW( pRes,
+ "lookupAttributableShape(): shape found does not implement AttributableShape interface" );
+
+ return pRes;
+ }
+
+ bool isIndefiniteTiming( const uno::Any& rAny )
+ {
+ if( !rAny.hasValue() )
+ return true;
+
+ animations::Timing eTiming;
+
+ if( !(rAny >>= eTiming) ||
+ eTiming != animations::Timing_INDEFINITE )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /// Extract the node type from the user data
+ bool getNodeType( sal_Int16& o_rNodeType,
+ const uno::Sequence< beans::NamedValue >& rValues )
+ {
+ beans::NamedValue aNamedValue;
+
+ if( findNamedValue( &aNamedValue,
+ rValues,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("node-type") ) ) )
+ {
+ if( (aNamedValue.Value >>= o_rNodeType) )
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/nodetools.hxx b/slideshow/source/engine/animationnodes/nodetools.hxx
new file mode 100644
index 000000000000..ed02ddc24a06
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/nodetools.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_NODETOOLS_HXX
+#define INCLUDED_SLIDESHOW_NODETOOLS_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+
+#include "shapemanager.hxx"
+#include "basenode.hxx"
+#include "doctreenode.hxx"
+#include "attributableshape.hxx"
+
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+# define DEBUG_NODES_SHOWTREE(a) debugNodesShowTree(a);
+# define DEBUG_NODES_SHOWTREE_WITHIN(a) debugNodesShowTreeWithin(a);
+#else
+# define DEBUG_NODES_SHOWTREE(a)
+# define DEBUG_NODES_SHOWTREE_WITHIN(a)
+#endif
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ // Tools
+ //=========================================================================
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ int& debugGetCurrentOffset();
+ void debugNodesShowTree( const BaseNode* );
+ void debugNodesShowTreeWithin( const BaseNode* );
+#endif
+
+ /** Look up an AttributableShape from ShapeManager.
+
+ This method retrieves an AttributableShape pointer, given
+ an XShape and a LayerManager.
+
+ Throws a runtime exception if there's no such shape, or if
+ it does not implement the AttributableShape interface.
+ */
+ AttributableShapeSharedPtr lookupAttributableShape( const ShapeManagerSharedPtr& rShapeManager,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape );
+
+ /** Predicate whether a Begin, Duration or End timing is
+ indefinite, i.e. either contains no value, or the
+ value Timing_INDEFINITE.
+ */
+ bool isIndefiniteTiming( const ::com::sun::star::uno::Any& rAny );
+
+ /// Extract the node type from the user data
+ bool getNodeType( sal_Int16& o_rNodeType,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::NamedValue >& rValues );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_NODETOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/paralleltimecontainer.cxx b/slideshow/source/engine/animationnodes/paralleltimecontainer.cxx
new file mode 100644
index 000000000000..766c0e9ad3cb
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/paralleltimecontainer.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include "paralleltimecontainer.hxx"
+#include "delayevent.hxx"
+
+#include <boost/bind.hpp>
+
+namespace slideshow {
+namespace internal {
+
+void ParallelTimeContainer::activate_st()
+{
+ // resolve all children:
+ std::size_t const nResolvedNodes =
+ static_cast<std::size_t>(std::count_if(
+ maChildren.begin(), maChildren.end(),
+ boost::mem_fn(&AnimationNode::resolve) ));
+ (void) nResolvedNodes; // avoid warning
+ OSL_ENSURE( nResolvedNodes == maChildren.size(),
+ "### resolving all children failed!" );
+
+ if (isDurationIndefinite() && maChildren.empty()) {
+ // deactivate ASAP:
+ scheduleDeactivationEvent(
+ makeEvent( boost::bind( &AnimationNode::deactivate, getSelf() ),
+ "ParallelTimeContainer::deactivate") );
+ }
+ else { // use default
+ scheduleDeactivationEvent();
+ }
+}
+
+void ParallelTimeContainer::notifyDeactivating(
+ AnimationNodeSharedPtr const& pChildNode )
+{
+ notifyDeactivatedChild( pChildNode );
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/paralleltimecontainer.hxx b/slideshow/source/engine/animationnodes/paralleltimecontainer.hxx
new file mode 100644
index 000000000000..3387ca8b64b1
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/paralleltimecontainer.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_PARALLELTIMECONTAINER_HXX
+#define INCLUDED_SLIDESHOW_PARALLELTIMECONTAINER_HXX
+
+#include "basecontainernode.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** This class implements parallel node containers
+
+ All children of this node are played in parallel
+*/
+class ParallelTimeContainer : public BaseContainerNode
+{
+public:
+ ParallelTimeContainer(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xNode,
+ const BaseContainerNodeSharedPtr& rParent,
+ const NodeContext& rContext )
+ : BaseContainerNode( xNode, rParent, rContext ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const
+ { return "ParallelTimeContainer"; }
+#endif
+
+private:
+ virtual void activate_st();
+ virtual void notifyDeactivating( AnimationNodeSharedPtr const& pChildNode );
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_PARALLELTIMECONTAINER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/propertyanimationnode.cxx b/slideshow/source/engine/animationnodes/propertyanimationnode.cxx
new file mode 100644
index 000000000000..288a9b87c11e
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/propertyanimationnode.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "propertyanimationnode.hxx"
+#include "animationfactory.hxx"
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+AnimationActivitySharedPtr PropertyAnimationNode::createActivity() const
+{
+ // Create AnimationActivity from common XAnimate parameters:
+ ActivitiesFactory::CommonParameters aParms( fillCommonParameters() );
+ uno::Reference<animations::XAnimate> const& xAnimateNode =getXAnimateNode();
+ rtl::OUString const attrName( xAnimateNode->getAttributeName() );
+ AttributableShapeSharedPtr const pShape( getShape() );
+
+ switch (AnimationFactory::classifyAttributeName( attrName )) {
+ default:
+ case AnimationFactory::CLASS_UNKNOWN_PROPERTY:
+ ENSURE_OR_THROW(
+ false,
+ "Unexpected attribute class (unknown or empty attribute name)" );
+ break;
+
+ case AnimationFactory::CLASS_NUMBER_PROPERTY:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createNumberPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ xAnimateNode );
+
+ case AnimationFactory::CLASS_ENUM_PROPERTY:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createEnumPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ xAnimateNode );
+
+ case AnimationFactory::CLASS_COLOR_PROPERTY:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createColorPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ xAnimateNode );
+
+ case AnimationFactory::CLASS_STRING_PROPERTY:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createStringPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ xAnimateNode );
+
+ case AnimationFactory::CLASS_BOOL_PROPERTY:
+ return ActivitiesFactory::createAnimateActivity(
+ aParms,
+ AnimationFactory::createBoolPropertyAnimation(
+ attrName,
+ pShape,
+ getContext().mpSubsettableShapeManager,
+ getSlideSize() ),
+ xAnimateNode );
+ }
+
+ return AnimationActivitySharedPtr();
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/propertyanimationnode.hxx b/slideshow/source/engine/animationnodes/propertyanimationnode.hxx
new file mode 100644
index 000000000000..8c542774dd9b
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/propertyanimationnode.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_PROPERTYANIMATIONNODE_HXX
+#define INCLUDED_SLIDESHOW_PROPERTYANIMATIONNODE_HXX
+
+#include "animationbasenode.hxx"
+
+namespace slideshow {
+namespace internal {
+
+class PropertyAnimationNode : public AnimationBaseNode
+{
+public:
+ PropertyAnimationNode(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ ::boost::shared_ptr<BaseContainerNode> const& pParent,
+ NodeContext const& rContext )
+ : AnimationBaseNode( xNode, pParent, rContext ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const
+ { return "PropertyAnimationNode"; }
+#endif
+
+private:
+ virtual AnimationActivitySharedPtr createActivity() const;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_PROPERTYANIMATIONNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/sequentialtimecontainer.cxx b/slideshow/source/engine/animationnodes/sequentialtimecontainer.cxx
new file mode 100644
index 000000000000..1fab09442990
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/sequentialtimecontainer.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include "delayevent.hxx"
+#include "eventqueue.hxx"
+#include "usereventqueue.hxx"
+#include "sequentialtimecontainer.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+namespace slideshow {
+namespace internal {
+
+void SequentialTimeContainer::activate_st()
+{
+ // resolve first possible child, ignore
+ for ( ; mnFinishedChildren < maChildren.size(); ++mnFinishedChildren ) {
+ if (resolveChild( maChildren[mnFinishedChildren] ))
+ break;
+ else {
+ // node still UNRESOLVED, no need to deactivate or end...
+ OSL_ENSURE( false, "### resolving child failed!" );
+ }
+ }
+
+ if (isDurationIndefinite() &&
+ (maChildren.empty() || mnFinishedChildren >= maChildren.size()))
+ {
+ // deactivate ASAP:
+ scheduleDeactivationEvent(
+ makeEvent(
+ boost::bind< void >( boost::mem_fn( &AnimationNode::deactivate ), getSelf() ),
+ "SequentialTimeContainer::deactivate") );
+ }
+ else // use default
+ scheduleDeactivationEvent();
+}
+
+void SequentialTimeContainer::dispose()
+{
+ BaseContainerNode::dispose();
+ if (mpCurrentSkipEvent) {
+ mpCurrentSkipEvent->dispose();
+ mpCurrentSkipEvent.reset();
+ }
+ if (mpCurrentRewindEvent) {
+ mpCurrentRewindEvent->dispose();
+ mpCurrentRewindEvent.reset();
+ }
+}
+
+void SequentialTimeContainer::skipEffect(
+ AnimationNodeSharedPtr const& pChildNode )
+{
+ if (isChildNode(pChildNode)) {
+ // empty all events ignoring timings => until next effect
+ getContext().mrEventQueue.forceEmpty();
+ getContext().mrEventQueue.addEvent(
+ makeEvent(
+ boost::bind<void>( boost::mem_fn( &AnimationNode::deactivate ), pChildNode ),
+ "SequentialTimeContainer::deactivate, skipEffect with delay") );
+ }
+ else
+ OSL_ENSURE( false, "unknown notifier!" );
+}
+
+void SequentialTimeContainer::rewindEffect(
+ AnimationNodeSharedPtr const& /*pChildNode*/ )
+{
+ // xxx todo: ...
+}
+
+bool SequentialTimeContainer::resolveChild(
+ AnimationNodeSharedPtr const& pChildNode )
+{
+ bool const bResolved = pChildNode->resolve();
+ if (bResolved && isMainSequenceRootNode()) {
+ // discharge events:
+ if (mpCurrentSkipEvent)
+ mpCurrentSkipEvent->dispose();
+ if (mpCurrentRewindEvent)
+ mpCurrentRewindEvent->dispose();
+
+ // event that will deactivate the resolved/running child:
+ mpCurrentSkipEvent = makeEvent(
+ boost::bind( &SequentialTimeContainer::skipEffect,
+ boost::dynamic_pointer_cast<SequentialTimeContainer>( getSelf() ),
+ pChildNode ),
+ "SequentialTimeContainer::skipEffect, resolveChild");
+ // event that will reresolve the resolved/activated child:
+ mpCurrentRewindEvent = makeEvent(
+ boost::bind( &SequentialTimeContainer::rewindEffect,
+ boost::dynamic_pointer_cast<SequentialTimeContainer>( getSelf() ),
+ pChildNode ),
+ "SequentialTimeContainer::rewindEffect, resolveChild");
+
+ // deactivate child node when skip event occurs:
+ getContext().mrUserEventQueue.registerSkipEffectEvent(
+ mpCurrentSkipEvent,
+ mnFinishedChildren+1<maChildren.size());
+ // rewind to previous child:
+ getContext().mrUserEventQueue.registerRewindEffectEvent(
+ mpCurrentRewindEvent );
+ }
+ return bResolved;
+}
+
+void SequentialTimeContainer::notifyDeactivating(
+ AnimationNodeSharedPtr const& rNotifier )
+{
+ if (notifyDeactivatedChild( rNotifier ))
+ return;
+
+ OSL_ASSERT( mnFinishedChildren < maChildren.size() );
+ AnimationNodeSharedPtr const& pNextChild = maChildren[mnFinishedChildren];
+ OSL_ASSERT( pNextChild->getState() == UNRESOLVED );
+
+ if (! resolveChild( pNextChild )) {
+ // could not resolve child - since we risk to
+ // stall the chain of events here, play it safe
+ // and deactivate this node (only if we have
+ // indefinite duration - otherwise, we'll get a
+ // deactivation event, anyways).
+ deactivate();
+ }
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/sequentialtimecontainer.hxx b/slideshow/source/engine/animationnodes/sequentialtimecontainer.hxx
new file mode 100644
index 000000000000..878b0f34f4f0
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/sequentialtimecontainer.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_SEQUENTIALTIMECONTAINER_HXX
+#define INCLUDED_SLIDESHOW_SEQUENTIALTIMECONTAINER_HXX
+
+#include "basecontainernode.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** This class implements sequential node containers
+
+ All children of this node are played sequentially
+*/
+class SequentialTimeContainer : public BaseContainerNode
+{
+public:
+ SequentialTimeContainer(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode> const& xNode,
+ BaseContainerNodeSharedPtr const& pParent,
+ NodeContext const& rContext )
+ : BaseContainerNode( xNode, pParent, rContext ) {}
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ virtual const char* getDescription() const
+ { return "SequentialTimeContainer"; }
+#endif
+
+protected:
+ virtual void dispose();
+
+private:
+ virtual void activate_st();
+ virtual void notifyDeactivating( AnimationNodeSharedPtr const& rNotifier );
+
+ void skipEffect( AnimationNodeSharedPtr const& pChildNode );
+ void rewindEffect( AnimationNodeSharedPtr const& pChildNode );
+
+private:
+ bool resolveChild( AnimationNodeSharedPtr const& pChildNode );
+
+ EventSharedPtr mpCurrentSkipEvent;
+ EventSharedPtr mpCurrentRewindEvent;
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_SEQUENTIALTIMECONTAINER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/animationnodes/setactivity.hxx b/slideshow/source/engine/animationnodes/setactivity.hxx
new file mode 100644
index 000000000000..76d750f2b337
--- /dev/null
+++ b/slideshow/source/engine/animationnodes/setactivity.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_SETACTIVITY_HXX
+#define INCLUDED_SLIDESHOW_SETACTIVITY_HXX
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include "animationactivity.hxx"
+#include "animation.hxx"
+#include "animatableshape.hxx"
+#include "shapeattributelayer.hxx"
+#include "activitiesfactory.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** Templated setter for animation values
+
+ This template class implements the AnimationActivity
+ interface, but only the perform() and
+ setAttributeLayer() methods are functional. To be used for set animations.
+
+ @see AnimationSetNode.
+*/
+template <class AnimationT>
+class SetActivity : public AnimationActivity
+{
+public:
+ typedef ::boost::shared_ptr< AnimationT > AnimationSharedPtrT;
+ typedef typename AnimationT::ValueType ValueT;
+
+ SetActivity( const ActivitiesFactory::CommonParameters& rParms,
+ const AnimationSharedPtrT& rAnimation,
+ const ValueT& rToValue )
+ : mpAnimation( rAnimation ),
+ mpShape(),
+ mpAttributeLayer(),
+ mpEndEvent( rParms.mpEndEvent ),
+ mrEventQueue( rParms.mrEventQueue ),
+ maToValue( rToValue ),
+ mbIsActive(true)
+ {
+ ENSURE_OR_THROW( mpAnimation, "Invalid animation" );
+ }
+
+ virtual void dispose()
+ {
+ mbIsActive = false;
+ mpAnimation.reset();
+ mpShape.reset();
+ mpAttributeLayer.reset();
+ // discharge end event:
+ if (mpEndEvent && mpEndEvent->isCharged())
+ mpEndEvent->dispose();
+ mpEndEvent.reset();
+ }
+
+ virtual double calcTimeLag() const
+ {
+ return 0.0;
+ }
+
+ virtual bool perform()
+ {
+ if (! isActive())
+ return false;
+ // we're going inactive immediately:
+ mbIsActive = false;
+
+ if (mpAnimation && mpAttributeLayer && mpShape) {
+ mpAnimation->start( mpShape, mpAttributeLayer );
+ (*mpAnimation)(maToValue);
+ mpAnimation->end();
+ }
+ // fire end event, if any
+ if (mpEndEvent)
+ mrEventQueue.addEvent( mpEndEvent );
+
+ return false; // don't reinsert
+ }
+
+ virtual bool isActive() const
+ {
+ return mbIsActive;
+ }
+
+ virtual void dequeued()
+ {
+ }
+
+ virtual void end()
+ {
+ perform();
+ }
+
+ virtual void setTargets( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+ {
+ ENSURE_OR_THROW( rShape, "Invalid shape" );
+ ENSURE_OR_THROW( rAttrLayer, "Invalid attribute layer" );
+
+ mpShape = rShape;
+ mpAttributeLayer = rAttrLayer;
+ }
+
+private:
+ AnimationSharedPtrT mpAnimation;
+ AnimatableShapeSharedPtr mpShape;
+ ShapeAttributeLayerSharedPtr mpAttributeLayer;
+ EventSharedPtr mpEndEvent;
+ EventQueue& mrEventQueue;
+ ValueT maToValue;
+ bool mbIsActive;
+};
+
+template <class AnimationT> AnimationActivitySharedPtr makeSetActivity(
+ const ActivitiesFactory::CommonParameters& rParms,
+ const ::boost::shared_ptr< AnimationT >& rAnimation,
+ const typename AnimationT::ValueType& rToValue )
+{
+ return AnimationActivitySharedPtr(
+ new SetActivity<AnimationT>(rParms,rAnimation,rToValue) );
+}
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_SETACTIVITY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/arith-grammar.txt b/slideshow/source/engine/arith-grammar.txt
new file mode 100644
index 000000000000..b12d320ef3bf
--- /dev/null
+++ b/slideshow/source/engine/arith-grammar.txt
@@ -0,0 +1,61 @@
+Based on the C grammar for arithmetic expressions
+=================================================
+
+number_digit = '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
+
+number_exponent = 'e'|'E'
+
+basic_number = basic_number number_digit | number_digit
+
+number =
+ basic_number |
+
+ basic_number number_exponent basic_number |
+ basic_number number_exponent '-' basic_number |
+ basic_number number_exponent '+' basic_number |
+
+ '.' basic_number number_exponent basic_number |
+ '.' basic_number number_exponent '-' basic_number |
+ '.' basic_number number_exponent '+' basic_number |
+
+ basic_number '.' number_exponent basic_number |
+ basic_number '.' number_exponent '-' basic_number |
+ basic_number '.' number_exponent '+' basic_number |
+
+ basic_number '.' basic_number number_exponent basic_number |
+ basic_number '.' basic_number number_exponent '-' basic_number |
+ basic_number '.' basic_number number_exponent '+' basic_number
+
+
+identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
+ ^ ^ ^ ^ ^
+ | | | | |
+ '$' in PPT | | | |
+ '#ppt_x' in PPT | | |
+ '#ppt_y' in PPT | |
+ '#ppt_w' in PPT |
+ '#ppt_h' in PPT
+
+unary_function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
+binary_function = 'min'|'max'
+
+
+basic_expression =
+ number |
+ identifier |
+ unary_function '(' additive_expression ')' |
+ binary_function '(' additive_expression ',' additive_expression ')' |
+ '(' additive_expression ')'
+
+unary_expression = '-' basic_expression
+
+multiplicative_expression =
+ basic_expression |
+ multiplicative_expression '*' basic_expression |
+ multiplicative_expression '/' basic_expression
+
+additive_expression =
+ multiplicative_expression |
+ additive_expression '+' multiplicative_expression |
+ additive_expression '-' multiplicative_expression
+
diff --git a/slideshow/source/engine/attributemap.cxx b/slideshow/source/engine/attributemap.cxx
new file mode 100644
index 000000000000..550961233ca3
--- /dev/null
+++ b/slideshow/source/engine/attributemap.cxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/canvastools.hxx>
+
+#include "attributemap.hxx"
+#include "tools.hxx"
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ typedef ::canvas::tools::ValueMap< AttributeType > AnimateAttributeMap;
+
+ AttributeType mapAttributeName( const ::rtl::OUString& rAttrName )
+ {
+ /** Maps attribute name to AttributeType enum.
+
+ String entries are all case-insensitive and MUST
+ BE STORED lowercase.
+
+ String entries MUST BE SORTED in ascending order!
+ */
+ static AnimateAttributeMap::MapEntry lcl_attributeMap[] =
+ {
+ { "charcolor", ATTRIBUTE_CHAR_COLOR },
+
+ { "charfontname", ATTRIBUTE_CHAR_FONT_NAME },
+
+ { "charheight", ATTRIBUTE_CHAR_HEIGHT },
+
+ { "charposture", ATTRIBUTE_CHAR_POSTURE },
+
+ // TODO(Q1): This should prolly be changed in PPT import
+ // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
+ { "charrotation", ATTRIBUTE_ROTATE },
+
+ { "charunderline", ATTRIBUTE_CHAR_UNDERLINE },
+
+ { "charweight", ATTRIBUTE_CHAR_WEIGHT },
+
+ { "color", ATTRIBUTE_COLOR },
+
+ { "dimcolor", ATTRIBUTE_DIMCOLOR },
+
+ { "fillcolor", ATTRIBUTE_FILL_COLOR },
+
+ { "fillstyle", ATTRIBUTE_FILL_STYLE },
+
+ { "height", ATTRIBUTE_HEIGHT },
+
+ { "linecolor", ATTRIBUTE_LINE_COLOR },
+
+ { "linestyle", ATTRIBUTE_LINE_STYLE },
+
+ { "opacity", ATTRIBUTE_OPACITY },
+
+ { "rotate", ATTRIBUTE_ROTATE },
+
+ { "skewx", ATTRIBUTE_SKEW_X },
+
+ { "skewy", ATTRIBUTE_SKEW_Y },
+
+ { "visibility", ATTRIBUTE_VISIBILITY },
+
+ { "width", ATTRIBUTE_WIDTH },
+
+ { "x", ATTRIBUTE_POS_X },
+
+ { "y", ATTRIBUTE_POS_Y }
+ };
+
+ static AnimateAttributeMap aMap( lcl_attributeMap,
+ sizeof(lcl_attributeMap)/sizeof(*lcl_attributeMap),
+ false );
+
+ AttributeType eAttributeType = ATTRIBUTE_INVALID;
+
+ // determine the type from the attribute name
+ if( !aMap.lookup( rAttrName,
+ eAttributeType ) )
+ {
+ OSL_TRACE( "mapAttributeName(): attribute name %s not found in map.",
+ ::rtl::OUStringToOString( rAttrName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+ return ATTRIBUTE_INVALID;
+ }
+
+ return eAttributeType;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/color.cxx b/slideshow/source/engine/color.cxx
new file mode 100644
index 000000000000..f20f17f0d18d
--- /dev/null
+++ b/slideshow/source/engine/color.cxx
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <hslcolor.hxx>
+#include <rgbcolor.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+
+#include <cmath> // for fmod
+#include <algorithm>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ namespace
+ {
+ // helper functions
+ // ================
+
+ double getMagic( double nLuminance, double nSaturation )
+ {
+ if( nLuminance <= 0.5 )
+ return nLuminance*(1.0 + nSaturation);
+ else
+ return nLuminance + nSaturation - nLuminance*nSaturation;
+ }
+
+ HSLColor::HSLTriple rgb2hsl( double nRed, double nGreen, double nBlue )
+ {
+ // r,g,b in [0,1], h in [0,360] and s,l in [0,1]
+ HSLColor::HSLTriple aRes;
+
+ const double nMax( ::std::max(nRed,::std::max(nGreen, nBlue)) );
+ const double nMin( ::std::min(nRed,::std::min(nGreen, nBlue)) );
+
+ const double nDelta( nMax - nMin );
+
+ aRes.mnLuminance = (nMax + nMin) / 2.0;
+
+ if( ::basegfx::fTools::equalZero( nDelta ) )
+ {
+ aRes.mnSaturation = 0.0;
+
+ // hue undefined (achromatic case)
+ aRes.mnHue = 0.0;
+ }
+ else
+ {
+ aRes.mnSaturation = aRes.mnLuminance > 0.5 ?
+ nDelta/(2.0-nMax-nMin) :
+ nDelta/(nMax + nMin);
+
+ if( nRed == nMax )
+ aRes.mnHue = (nGreen - nBlue)/nDelta;
+ else if( nGreen == nMax )
+ aRes.mnHue = 2.0 + (nBlue - nRed)/nDelta;
+ else if( nBlue == nMax )
+ aRes.mnHue = 4.0 + (nRed - nGreen)/nDelta;
+
+ aRes.mnHue *= 60.0;
+
+ if( aRes.mnHue < 0.0 )
+ aRes.mnHue += 360.0;
+ }
+
+ return aRes;
+ }
+
+ double hsl2rgbHelper( double nValue1, double nValue2, double nHue )
+ {
+ // clamp hue to [0,360]
+ nHue = fmod( nHue, 360.0 );
+
+ // cope with wrap-arounds
+ if( nHue < 0.0 )
+ nHue += 360.0;
+
+ if( nHue < 60.0 )
+ return nValue1 + (nValue2 - nValue1)*nHue/60.0;
+ else if( nHue < 180.0 )
+ return nValue2;
+ else if( nHue < 240.0 )
+ return nValue1 + (nValue2 - nValue1)*(240.0 - nHue)/60.0;
+ else
+ return nValue1;
+ }
+
+ RGBColor::RGBTriple hsl2rgb( double nHue, double nSaturation, double nLuminance )
+ {
+ if( ::basegfx::fTools::equalZero( nSaturation ) )
+ return RGBColor::RGBTriple(0.0, 0.0, nLuminance );
+
+ const double nVal1( getMagic(nLuminance, nSaturation) );
+ const double nVal2( 2.0*nLuminance - nVal1 );
+
+ RGBColor::RGBTriple aRes;
+
+ aRes.mnRed = hsl2rgbHelper( nVal2,
+ nVal1,
+ nHue + 120.0 );
+ aRes.mnGreen = hsl2rgbHelper( nVal2,
+ nVal1,
+ nHue );
+ aRes.mnBlue = hsl2rgbHelper( nVal2,
+ nVal1,
+ nHue - 120.0 );
+
+ return aRes;
+ }
+
+ /// Truncate range of value to [0,1]
+ double truncateRangeStd( double nVal )
+ {
+ return ::std::max( 0.0,
+ ::std::min( 1.0,
+ nVal ) );
+ }
+
+ /// Truncate range of value to [0,360]
+ double truncateRangeHue( double nVal )
+ {
+ return ::std::max( 0.0,
+ ::std::min( 360.0,
+ nVal ) );
+ }
+
+ /// convert RGB color to sal_uInt8, truncate range appropriately before
+ sal_uInt8 colorToInt( double nCol )
+ {
+ return static_cast< sal_uInt8 >(
+ ::basegfx::fround( truncateRangeStd( nCol ) * 255.0 ) );
+ }
+ }
+
+
+
+ // HSLColor
+ // ===============================================
+
+ HSLColor::HSLTriple::HSLTriple() :
+ mnHue(),
+ mnSaturation(),
+ mnLuminance()
+ {
+ }
+
+ HSLColor::HSLTriple::HSLTriple( double nHue, double nSaturation, double nLuminance ) :
+ mnHue( nHue ),
+ mnSaturation( nSaturation ),
+ mnLuminance( nLuminance )
+ {
+ }
+
+ HSLColor::HSLColor() :
+ maHSLTriple( 0.0, 0.0, 0.0 ),
+ mnMagicValue( getMagic( maHSLTriple.mnLuminance,
+ maHSLTriple.mnSaturation ) )
+ {
+ }
+
+ HSLColor::HSLColor( ::cppcanvas::Color::IntSRGBA nRGBColor ) :
+ maHSLTriple( rgb2hsl( ::cppcanvas::getRed( nRGBColor ) / 255.0,
+ ::cppcanvas::getGreen( nRGBColor ) / 255.0,
+ ::cppcanvas::getBlue( nRGBColor ) / 255.0 ) ),
+ mnMagicValue( getMagic( maHSLTriple.mnLuminance,
+ maHSLTriple.mnSaturation ) )
+ {
+ }
+
+ HSLColor::HSLColor( double nHue, double nSaturation, double nLuminance ) :
+ maHSLTriple( nHue, nSaturation, nLuminance ),
+ mnMagicValue( getMagic( maHSLTriple.mnLuminance,
+ maHSLTriple.mnSaturation ) )
+ {
+ }
+
+ HSLColor::HSLColor( const RGBColor& rColor ) :
+ maHSLTriple( rgb2hsl( truncateRangeStd( rColor.getRed() ),
+ truncateRangeStd( rColor.getGreen() ),
+ truncateRangeStd( rColor.getBlue() ) ) ),
+ mnMagicValue( getMagic( maHSLTriple.mnLuminance,
+ maHSLTriple.mnSaturation ) )
+ {
+ }
+
+ double HSLColor::getHue() const
+ {
+ return maHSLTriple.mnHue;
+ }
+
+ double HSLColor::getSaturation() const
+ {
+ return maHSLTriple.mnSaturation;
+ }
+
+ double HSLColor::getLuminance() const
+ {
+ return maHSLTriple.mnLuminance;
+ }
+
+ double HSLColor::getRed() const
+ {
+ if( ::basegfx::fTools::equalZero( getSaturation() ) )
+ return getLuminance();
+
+ return hsl2rgbHelper( 2.0*getLuminance() - mnMagicValue,
+ mnMagicValue,
+ getHue() + 120.0 );
+ }
+
+ double HSLColor::getGreen() const
+ {
+ if( ::basegfx::fTools::equalZero( getSaturation() ) )
+ return getLuminance();
+
+ return hsl2rgbHelper( 2.0*getLuminance() - mnMagicValue,
+ mnMagicValue,
+ getHue() );
+ }
+
+ double HSLColor::getBlue() const
+ {
+ if( ::basegfx::fTools::equalZero( getSaturation() ) )
+ return getLuminance();
+
+ return hsl2rgbHelper( 2.0*getLuminance() - mnMagicValue,
+ mnMagicValue,
+ getHue() - 120.0 );
+ }
+
+ RGBColor HSLColor::getRGBColor() const
+ {
+ RGBColor::RGBTriple aColor( hsl2rgb( getHue(),
+ getSaturation(),
+ getLuminance() ) );
+ return RGBColor( aColor.mnRed, aColor.mnGreen, aColor.mnBlue );
+ }
+
+ RGBColor::RGBColor(const RGBColor& rLHS)
+ : maRGBTriple( rLHS.maRGBTriple )
+ {
+ }
+
+ RGBColor& RGBColor::operator=( const RGBColor& rLHS ){
+
+ maRGBTriple.mnRed = rLHS.getRed();
+ maRGBTriple.mnGreen = rLHS.getGreen();
+ maRGBTriple.mnBlue = rLHS.getBlue();
+ return *this;
+ }
+
+ HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS )
+ {
+ return HSLColor( rLHS.getHue() + rRHS.getHue(),
+ rLHS.getSaturation() + rRHS.getSaturation(),
+ rLHS.getLuminance() + rRHS.getLuminance() );
+ }
+
+ HSLColor operator*( const HSLColor& rLHS, const HSLColor& rRHS )
+ {
+ return HSLColor( rLHS.getHue() * rRHS.getHue(),
+ rLHS.getSaturation() * rRHS.getSaturation(),
+ rLHS.getLuminance() * rRHS.getLuminance() );
+ }
+
+ HSLColor operator*( double nFactor, const HSLColor& rRHS )
+ {
+ return HSLColor( nFactor * rRHS.getHue(),
+ nFactor * rRHS.getSaturation(),
+ nFactor * rRHS.getLuminance() );
+ }
+
+ HSLColor interpolate( const HSLColor& rFrom, const HSLColor& rTo, double t, bool bCCW )
+ {
+ const double nFromHue( rFrom.getHue() );
+ const double nToHue ( rTo.getHue() );
+
+ double nHue=0.0;
+
+ if( nFromHue <= nToHue && !bCCW )
+ {
+ // interpolate hue clockwise. That is, hue starts at
+ // high values and ends at low ones. Therefore, we
+ // must 'cross' the 360 degrees and start at low
+ // values again (imagine the hues to lie on the
+ // circle, where values above 360 degrees are mapped
+ // back to [0,360)).
+ nHue = (1.0-t)*(nFromHue + 360.0) + t*nToHue;
+ }
+ else if( nFromHue > nToHue && bCCW )
+ {
+ // interpolate hue counter-clockwise. That is, hue
+ // starts at high values and ends at low
+ // ones. Therefore, we must 'cross' the 360 degrees
+ // and start at low values again (imagine the hues to
+ // lie on the circle, where values above 360 degrees
+ // are mapped back to [0,360)).
+ nHue = (1.0-t)*nFromHue + t*(nToHue + 360.0);
+ }
+ else
+ {
+ // interpolate hue counter-clockwise. That is, hue
+ // starts at low values and ends at high ones (imagine
+ // the hue value as degrees on a circle, with
+ // increasing values going counter-clockwise)
+ nHue = (1.0-t)*nFromHue + t*nToHue;
+ }
+
+ return HSLColor( nHue,
+ (1.0-t)*rFrom.getSaturation() + t*rTo.getSaturation(),
+ (1.0-t)*rFrom.getLuminance() + t*rTo.getLuminance() );
+ }
+
+
+
+ // RGBColor
+ // ===============================================
+
+
+ RGBColor::RGBTriple::RGBTriple() :
+ mnRed(),
+ mnGreen(),
+ mnBlue()
+ {
+ }
+
+ RGBColor::RGBTriple::RGBTriple( double nRed, double nGreen, double nBlue ) :
+ mnRed( nRed ),
+ mnGreen( nGreen ),
+ mnBlue( nBlue )
+ {
+ }
+
+ RGBColor::RGBColor() :
+ maRGBTriple( 0.0, 0.0, 0.0 )
+ {
+ }
+
+ RGBColor::RGBColor( ::cppcanvas::Color::IntSRGBA nRGBColor ) :
+ maRGBTriple( ::cppcanvas::getRed( nRGBColor ) / 255.0,
+ ::cppcanvas::getGreen( nRGBColor ) / 255.0,
+ ::cppcanvas::getBlue( nRGBColor ) / 255.0 )
+ {
+ }
+
+ RGBColor::RGBColor( double nRed, double nGreen, double nBlue ) :
+ maRGBTriple( nRed, nGreen, nBlue )
+ {
+ }
+
+ RGBColor::RGBColor( const HSLColor& rColor ) :
+ maRGBTriple( hsl2rgb( truncateRangeHue( rColor.getHue() ),
+ truncateRangeStd( rColor.getSaturation() ),
+ truncateRangeStd( rColor.getLuminance() ) ) )
+ {
+ }
+
+ double RGBColor::getHue() const
+ {
+ return rgb2hsl( getRed(),
+ getGreen(),
+ getBlue() ).mnHue;
+ }
+
+ double RGBColor::getSaturation() const
+ {
+ return rgb2hsl( getRed(),
+ getGreen(),
+ getBlue() ).mnSaturation;
+ }
+
+ double RGBColor::getLuminance() const
+ {
+ return rgb2hsl( getRed(),
+ getGreen(),
+ getBlue() ).mnLuminance;
+ }
+
+ double RGBColor::getRed() const
+ {
+ return maRGBTriple.mnRed;
+ }
+
+ double RGBColor::getGreen() const
+ {
+ return maRGBTriple.mnGreen;
+ }
+
+ double RGBColor::getBlue() const
+ {
+ return maRGBTriple.mnBlue;
+ }
+
+ HSLColor RGBColor::getHSLColor() const
+ {
+ HSLColor::HSLTriple aColor( rgb2hsl( getRed(),
+ getGreen(),
+ getBlue() ) );
+ return HSLColor( aColor.mnHue, aColor.mnSaturation, aColor.mnLuminance );
+ }
+
+ ::cppcanvas::Color::IntSRGBA RGBColor::getIntegerColor() const
+ {
+ return ::cppcanvas::makeColor( colorToInt( getRed() ),
+ colorToInt( getGreen() ),
+ colorToInt( getBlue() ),
+ 255 );
+ }
+
+ RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS )
+ {
+ return RGBColor( rLHS.getRed() + rRHS.getRed(),
+ rLHS.getGreen() + rRHS.getGreen(),
+ rLHS.getBlue() + rRHS.getBlue() );
+ }
+
+ RGBColor operator*( const RGBColor& rLHS, const RGBColor& rRHS )
+ {
+ return RGBColor( rLHS.getRed() * rRHS.getRed(),
+ rLHS.getGreen() * rRHS.getGreen(),
+ rLHS.getBlue() * rRHS.getBlue() );
+ }
+
+ RGBColor operator*( double nFactor, const RGBColor& rRHS )
+ {
+ return RGBColor( nFactor * rRHS.getRed(),
+ nFactor * rRHS.getGreen(),
+ nFactor * rRHS.getBlue() );
+ }
+
+ RGBColor interpolate( const RGBColor& rFrom, const RGBColor& rTo, double t )
+ {
+ return RGBColor( (1.0-t)*rFrom.getRed() + t*rTo.getRed(),
+ (1.0-t)*rFrom.getGreen() + t*rTo.getGreen(),
+ (1.0-t)*rFrom.getBlue() + t*rTo.getBlue() );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/debug.cxx b/slideshow/source/engine/debug.cxx
new file mode 100644
index 000000000000..1e5b312db489
--- /dev/null
+++ b/slideshow/source/engine/debug.cxx
@@ -0,0 +1,327 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_slideshow.hxx"
+
+#include "debug.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+
+#include "animationnodes/basecontainernode.hxx"
+#include "animationnodes/paralleltimecontainer.hxx"
+#include "animationnodes/sequentialtimecontainer.hxx"
+#include "animationnodes/animationtransitionfilternode.hxx"
+#include "animationnodes/animationaudionode.hxx"
+#include "animationnodes/animationcolornode.hxx"
+#include "animationnodes/animationcommandnode.hxx"
+#include "animationnodes/animationpathmotionnode.hxx"
+#include "animationnodes/animationsetnode.hxx"
+#include "animationnodes/animationtransformnode.hxx"
+#include "animationnodes/propertyanimationnode.hxx"
+
+#include <com/sun/star/animations/XAnimationNode.hpp>
+#include <com/sun/star/animations/Event.hpp>
+
+#include <cstdio>
+#include <cstdarg>
+
+using ::rtl::OUString;
+using namespace ::com::sun::star;
+
+
+namespace slideshow { namespace internal {
+
+namespace {
+
+class NodeContainer : public BaseContainerNode
+{
+public:
+ void ShowChildrenState (void) const;
+};
+
+
+
+
+OUString DebugGetDescription (const AnimationNodeSharedPtr& rpNode)
+{
+ if (::boost::dynamic_pointer_cast<BaseContainerNode>(rpNode))
+ {
+ // Node is a container.
+ if (::boost::dynamic_pointer_cast<ParallelTimeContainer>(rpNode))
+ return OUString::createFromAscii("ParallelTimeContainer");
+ else if (::boost::dynamic_pointer_cast<SequentialTimeContainer>(rpNode))
+ return OUString::createFromAscii("SequentialTimeContainer");
+ else
+ return OUString::createFromAscii("<unknown container>");
+ }
+ else if (::boost::dynamic_pointer_cast<AnimationTransitionFilterNode>(rpNode))
+ return OUString::createFromAscii("AnimationTransitionFilterNode");
+ else if (::boost::dynamic_pointer_cast<AnimationAudioNode>(rpNode))
+ return OUString::createFromAscii("AnimationAudioNode");
+ else if (::boost::dynamic_pointer_cast<AnimationColorNode>(rpNode))
+ return OUString::createFromAscii("AnimationColorNode");
+ else if (::boost::dynamic_pointer_cast<AnimationCommandNode>(rpNode))
+ return OUString::createFromAscii("AnimationCommandNode");
+ else if (::boost::dynamic_pointer_cast<AnimationPathMotionNode>(rpNode))
+ return OUString::createFromAscii("AnimationPathMotionNode");
+ else if (::boost::dynamic_pointer_cast<AnimationSetNode>(rpNode))
+ return OUString::createFromAscii("AnimationSetNode");
+ else if (::boost::dynamic_pointer_cast<AnimationTransformNode>(rpNode))
+ return OUString::createFromAscii("AnimationTransformNode");
+ else if (::boost::dynamic_pointer_cast<PropertyAnimationNode>(rpNode))
+ return OUString::createFromAscii("PropertyAnimationNode");
+ else
+ return OUString::createFromAscii("<unknown node type>");
+}
+
+
+
+
+void DebugShowState (const AnimationNodeSharedPtr& rpNode)
+{
+ if ( ! rpNode)
+ return;
+
+ OUString sState;
+ OUString sStateColor;
+ switch (rpNode->getState())
+ {
+ default:
+ case AnimationNode::INVALID:
+ sState = OUString::createFromAscii("Invalid");
+ sStateColor = OUString::createFromAscii("firebrick1");
+ break;
+ case AnimationNode::UNRESOLVED:
+ sState = OUString::createFromAscii("Unresolved");
+ sStateColor = OUString::createFromAscii("dodgerblue4");
+ break;
+ case AnimationNode::RESOLVED:
+ sState = OUString::createFromAscii("Resolved");
+ sStateColor = OUString::createFromAscii("dodgerblue");
+ break;
+ case AnimationNode::ACTIVE:
+ sState = OUString::createFromAscii("Active");
+ sStateColor = OUString::createFromAscii("seagreen1");
+ break;
+ case AnimationNode::FROZEN:
+ sState = OUString::createFromAscii("Frozen");
+ sStateColor = OUString::createFromAscii("lightskyblue1");
+ break;
+ case AnimationNode::ENDED:
+ sState = OUString::createFromAscii("Ended");
+ sStateColor = OUString::createFromAscii("slategray3");
+ break;
+ }
+
+ const uno::Any aBegin (rpNode->getXAnimationNode()->getBegin());
+ OUString sTrigger;
+ if (aBegin.hasValue())
+ {
+ animations::Event aEvent;
+ double nTimeOffset;
+ const static char* sEventTriggers[] = {
+ "NONE", "ON_BEGIN", "ON_END", "BEGIN_EVENT", "END_EVENT", "ON_CLICK",
+ "ON_DBL_CLICK", "ON_MOUSE_ENTER", "ON_MOUSE_LEAVE", "ON_NEXT", "ON_PREV",
+ "ON_STOP_AUDIO", "REPEAT"};
+ if (aBegin >>= aEvent)
+ {
+ sTrigger = OUString::createFromAscii(sEventTriggers[aEvent.Trigger]);
+ }
+ else if (aBegin >>= nTimeOffset)
+ {
+ sTrigger = OUString::valueOf(nTimeOffset);
+ }
+ else
+ {
+ sTrigger = OUString::createFromAscii("other");
+ }
+ }
+ else
+ sTrigger = ::rtl::OUString::createFromAscii("void");
+
+ TRACE("Node state: n%x [label=\"%x / %x / %s\\n%s\\n%s\",style=filled,fillcolor=\"%s\"]\r",
+ rpNode.get(),
+ rpNode.get(),
+ rpNode->getXAnimationNode().get(),
+ ::rtl::OUStringToOString(sState, RTL_TEXTENCODING_ASCII_US).getStr(),
+ ::rtl::OUStringToOString(DebugGetDescription(rpNode), RTL_TEXTENCODING_ASCII_US).getStr(),
+ ::rtl::OUStringToOString(sTrigger, RTL_TEXTENCODING_ASCII_US).getStr(),
+ ::rtl::OUStringToOString(sStateColor, RTL_TEXTENCODING_ASCII_US).getStr());
+
+ BaseContainerNodeSharedPtr pContainer (
+ ::boost::dynamic_pointer_cast<BaseContainerNode>(rpNode));
+ if (pContainer)
+ ::boost::static_pointer_cast<NodeContainer>(rpNode)->ShowChildrenState();
+}
+
+
+
+
+void NodeContainer::ShowChildrenState (void) const
+{
+ for (std::size_t nIndex=0; nIndex<maChildren.size(); ++nIndex)
+ {
+ TRACE("Node connection: n%x -> n%x", this, maChildren[nIndex].get());
+ DebugShowState(maChildren[nIndex]);
+ }
+}
+
+
+
+
+AnimationNodeSharedPtr DebugGetTreeRoot (const BaseNodeSharedPtr& rpNode)
+{
+ BaseNodeSharedPtr pNode (rpNode);
+ if (pNode)
+ {
+ BaseNodeSharedPtr pParent (pNode->getParentNode());
+ while (pParent)
+ {
+ pNode = pParent;
+ pParent = pNode->getParentNode();
+ }
+ }
+ return pNode;
+}
+
+} // end of anonymous namespace
+
+
+
+
+void Debug_ShowNodeTree (const AnimationNodeSharedPtr& rpNode)
+{
+ DebugTraceScope aTraceScope ("NodeTree");
+
+ DebugShowState(DebugGetTreeRoot(::boost::dynamic_pointer_cast<BaseNode>(rpNode)));
+}
+
+
+
+
+//----- Tracing ---------------------------------------------------------------
+
+extern "C" {
+
+ namespace {
+
+ class TraceData
+ {
+ public:
+ TraceData (void)
+ : mnIndentation(0),
+ mpFile(fopen(TRACE_LOG_FILE_NAME, "w")),
+ maTime()
+ {
+ }
+
+ int mnIndentation;
+ FILE* mpFile;
+ ::canvas::tools::ElapsedTime maTime;
+ };
+ static TraceData gTraceData;
+
+ inline void SAL_CALL DebugTrace (
+ const int nIndentationOffset,
+ const sal_Char* sFormat,
+ va_list args)
+ {
+ if (gTraceData.mpFile != NULL)
+ {
+ // Write line head with current time and indentation.
+ // Adapt indentation.
+ if (nIndentationOffset < 0)
+ gTraceData.mnIndentation += nIndentationOffset;
+ fprintf(gTraceData.mpFile, "%10.8f ", gTraceData.maTime.getElapsedTime());
+ for (int nIndentation=0; nIndentation<gTraceData.mnIndentation; ++nIndentation)
+ fprintf(gTraceData.mpFile, " ");
+ if (nIndentationOffset > 0)
+ gTraceData.mnIndentation += nIndentationOffset;
+
+ // Write message.
+ vfprintf(gTraceData.mpFile, sFormat, args);
+ fprintf(gTraceData.mpFile, "\n");
+ fflush(gTraceData.mpFile);
+ }
+ }
+
+} // end of anonymous namespace
+
+
+} // end of extern "C"
+
+void SAL_CALL DebugTraceBegin (const sal_Char* sFormat, ...)
+{
+ va_list args;
+ va_start(args, sFormat);
+ DebugTrace(+1,sFormat, args);
+ va_end(args);
+}
+
+void SAL_CALL DebugTraceEnd (const sal_Char* sFormat, ...)
+{
+ va_list args;
+ va_start(args, sFormat);
+ DebugTrace(-1,sFormat, args);
+ va_end(args);
+}
+
+void SAL_CALL DebugTraceMessage (const sal_Char* sFormat, ...)
+{
+ va_list args;
+ va_start(args, sFormat);
+ DebugTrace(0,sFormat, args);
+ va_end(args);
+}
+
+
+
+DebugTraceScope::DebugTraceScope (const sal_Char* sFormat, ...)
+ : msMessage(new sal_Char[mnBufferSize])
+{
+ va_list args;
+ va_start(args, sFormat);
+
+ msMessage[mnBufferSize-1] = 0;
+ snprintf(msMessage, mnBufferSize-1, sFormat, args);
+ TRACE_BEGIN("[ %s", msMessage);
+ va_end(args);
+}
+
+DebugTraceScope::~DebugTraceScope (void)
+{
+ TRACE_END("] %s", msMessage);
+ delete [] msMessage;
+}
+
+
+} }
+
+#endif // OSL_DEBUG_LEVEL > 1
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/delayevent.cxx b/slideshow/source/engine/delayevent.cxx
new file mode 100644
index 000000000000..5c0defb79574
--- /dev/null
+++ b/slideshow/source/engine/delayevent.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <osl/diagnose.h>
+#include "delayevent.hxx"
+
+namespace slideshow {
+namespace internal {
+
+bool Delay::fire()
+{
+ OSL_ASSERT( isCharged() );
+ if (isCharged()) {
+ mbWasFired = true;
+ maFunc();
+ maFunc.clear(); // early release of payload
+ }
+ return true;
+}
+
+bool Delay::isCharged() const
+{
+ return !mbWasFired;
+}
+
+double Delay::getActivationTime( double nCurrentTime ) const
+{
+ return nCurrentTime + mnTimeout;
+}
+
+void Delay::dispose()
+{
+ // don't clear unconditionally, because it may currently be executed:
+ if (isCharged()) {
+ mbWasFired = true;
+ maFunc.clear(); // release of payload
+ }
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/effectrewinder.cxx b/slideshow/source/engine/effectrewinder.cxx
new file mode 100644
index 000000000000..a6d5c5120d51
--- /dev/null
+++ b/slideshow/source/engine/effectrewinder.cxx
@@ -0,0 +1,436 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_slideshow.hxx"
+
+#include "effectrewinder.hxx"
+#include "eventqueue.hxx"
+#include "usereventqueue.hxx"
+#include "mouseeventhandler.hxx"
+#include "animationnodes/basecontainernode.hxx"
+#include "delayevent.hxx"
+
+#include <com/sun/star/awt/MouseEvent.hpp>
+#include <com/sun/star/animations/Event.hpp>
+#include <com/sun/star/animations/EventTrigger.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+using ::com::sun::star::uno::Reference;
+using namespace ::com::sun::star;
+
+namespace slideshow { namespace internal {
+
+
+namespace {
+
+class RewinderEventHandler : public EventHandler
+{
+public:
+ typedef ::boost::function<bool(void)> Action;
+ RewinderEventHandler (const Action& rAction) : maAction(rAction) {}
+ virtual ~RewinderEventHandler (void) {}
+private:
+ const Action maAction;
+ virtual bool handleEvent (void) { return maAction(); }
+};
+
+
+
+class RewinderAnimationEventHandler : public AnimationEventHandler
+{
+public:
+ typedef ::boost::function<bool(const AnimationNodeSharedPtr& rpNode)> Action;
+ RewinderAnimationEventHandler (const Action& rAction) : maAction(rAction) {}
+ virtual ~RewinderAnimationEventHandler (void) {}
+private:
+ const Action maAction;
+ virtual bool handleAnimationEvent (const AnimationNodeSharedPtr& rpNode)
+ { return maAction(rpNode); }
+};
+
+
+
+} // end of anonymous namespace
+
+
+//----- EffectRewinder --------------------------------------------------------------
+
+EffectRewinder::EffectRewinder (
+ EventMultiplexer& rEventMultiplexer,
+ EventQueue& rEventQueue,
+ UserEventQueue& rUserEventQueue)
+ : mrEventMultiplexer(rEventMultiplexer),
+ mrEventQueue(rEventQueue),
+ mrUserEventQueue(rUserEventQueue),
+ mpSlideStartHandler(),
+ mpSlideEndHandler(),
+ mpAnimationStartHandler(),
+ mnMainSequenceEffectCount(0),
+ mpAsynchronousRewindEvent(),
+ mxCurrentAnimationRootNode(),
+ mbNonUserTriggeredMainSequenceEffectSeen(false)
+{
+ initialize();
+}
+
+
+
+
+void EffectRewinder::initialize (void)
+{
+ // Add some event handlers so that we are informed when
+ // a) an animation is started (we then check whether that belongs to a
+ // main sequence effect and if so, increase the respective counter),
+ // b,c) a slide was started or ended (in which case the effect counter
+ // is reset.
+
+ mpAnimationStartHandler.reset(
+ new RewinderAnimationEventHandler(
+ ::boost::bind(&EffectRewinder::notifyAnimationStart, this, _1)));
+ mrEventMultiplexer.addAnimationStartHandler(mpAnimationStartHandler);
+
+ mpSlideStartHandler.reset(
+ new RewinderEventHandler(
+ ::boost::bind(&EffectRewinder::resetEffectCount, this)));
+ mrEventMultiplexer.addSlideStartHandler(mpSlideStartHandler);
+
+ mpSlideEndHandler.reset(
+ new RewinderEventHandler(
+ ::boost::bind(&EffectRewinder::resetEffectCount, this)));
+ mrEventMultiplexer.addSlideEndHandler(mpSlideEndHandler);
+}
+
+
+
+
+EffectRewinder::~EffectRewinder (void)
+{
+ dispose();
+}
+
+
+
+
+void EffectRewinder::dispose (void)
+{
+ if (mpAsynchronousRewindEvent)
+ {
+ mpAsynchronousRewindEvent->dispose();
+ mpAsynchronousRewindEvent.reset();
+ }
+
+ if (mpAnimationStartHandler)
+ {
+ mrEventMultiplexer.removeAnimationStartHandler(mpAnimationStartHandler);
+ mpAnimationStartHandler.reset();
+ }
+
+ if (mpSlideStartHandler)
+ {
+ mrEventMultiplexer.removeSlideStartHandler(mpSlideStartHandler);
+ mpSlideStartHandler.reset();
+ }
+
+ if (mpSlideEndHandler)
+ {
+ mrEventMultiplexer.removeSlideEndHandler(mpSlideEndHandler);
+ mpSlideEndHandler.reset();
+ }
+}
+
+
+
+
+void EffectRewinder::setRootAnimationNode (
+ const uno::Reference<animations::XAnimationNode>& xRootNode)
+{
+ mxCurrentAnimationRootNode = xRootNode;
+}
+
+
+
+
+bool EffectRewinder::rewind (
+ const ::boost::shared_ptr<ScreenUpdater::UpdateLock>& rpPaintLock,
+ const ::boost::function<void(void)>& rSlideRewindFunctor,
+ const ::boost::function<void(void)>& rPreviousSlideFunctor)
+{
+ mpPaintLock = rpPaintLock;
+
+ // Do not allow nested rewinds.
+ if (mpAsynchronousRewindEvent)
+ {
+ OSL_ASSERT( ! mpAsynchronousRewindEvent);
+ return false;
+ }
+
+ // Abort (and skip over the rest of) any currently active animation.
+ mrUserEventQueue.callSkipEffectEventHandler();
+ mrEventQueue.forceEmpty();
+
+ const int nSkipCount (mnMainSequenceEffectCount - 1);
+ if (nSkipCount < 0)
+ {
+ if ( ! rPreviousSlideFunctor)
+ {
+ OSL_ASSERT(rPreviousSlideFunctor);
+ return false;
+ }
+
+ // No main sequence effects to rewind on the current slide.
+ // Go back to the previous slide.
+ mpAsynchronousRewindEvent = makeEvent(
+ ::boost::bind(
+ &EffectRewinder::asynchronousRewindToPreviousSlide,
+ this,
+ rPreviousSlideFunctor),
+ "EffectRewinder::asynchronousRewindToPreviousSlide");
+ }
+ else
+ {
+ // The actual rewinding is done asynchronously so that we can safely
+ // call other methods.
+ mpAsynchronousRewindEvent = makeEvent(
+ ::boost::bind(
+ &EffectRewinder::asynchronousRewind,
+ this,
+ nSkipCount,
+ true,
+ rSlideRewindFunctor),
+ "EffectRewinder::asynchronousRewind");
+ }
+
+ if (mpAsynchronousRewindEvent)
+ mrEventQueue.addEvent(mpAsynchronousRewindEvent);
+
+ return mpAsynchronousRewindEvent.get()!=NULL;
+}
+
+
+
+
+void EffectRewinder::skipAllMainSequenceEffects (void)
+{
+ // Do not allow nested rewinds.
+ if (mpAsynchronousRewindEvent)
+ {
+ OSL_ASSERT(!mpAsynchronousRewindEvent);
+ return;
+ }
+
+ const int nTotalMainSequenceEffectCount (countMainSequenceEffects());
+ mpAsynchronousRewindEvent = makeEvent(
+ ::boost::bind(
+ &EffectRewinder::asynchronousRewind,
+ this,
+ nTotalMainSequenceEffectCount,
+ false,
+ ::boost::function<void(void)>()),
+ "EffectRewinder::asynchronousRewind");
+ mrEventQueue.addEvent(mpAsynchronousRewindEvent);
+}
+
+
+
+
+sal_Int32 EffectRewinder::countMainSequenceEffects (void)
+{
+ // Determine the number of main sequence effects.
+ sal_Int32 nMainSequenceNodeCount (0);
+
+ ::std::queue<uno::Reference<animations::XAnimationNode> > aNodeQueue;
+ aNodeQueue.push(mxCurrentAnimationRootNode);
+ while ( ! aNodeQueue.empty())
+ {
+ const uno::Reference<animations::XAnimationNode> xNode (aNodeQueue.front());
+ aNodeQueue.pop();
+
+ // Does the current node belong to the main sequence?
+ if (xNode.is())
+ {
+ animations::Event aEvent;
+ if (xNode->getBegin() >>= aEvent)
+ if (aEvent.Trigger == animations::EventTrigger::ON_NEXT)
+ ++nMainSequenceNodeCount;
+ }
+
+ // If the current node is a container then prepare its children for investigation.
+ uno::Reference<container::XEnumerationAccess> xEnumerationAccess (xNode, uno::UNO_QUERY);
+ if (xEnumerationAccess.is())
+ {
+ uno::Reference<container::XEnumeration> xEnumeration (
+ xEnumerationAccess->createEnumeration());
+ if (xEnumeration.is())
+ while (xEnumeration->hasMoreElements())
+ {
+ aNodeQueue.push(
+ uno::Reference<animations::XAnimationNode>(
+ xEnumeration->nextElement(), uno::UNO_QUERY));
+ }
+ }
+ }
+
+ return nMainSequenceNodeCount;
+
+ // // Skip all main sequence nodes.
+ // SkipSomeMainSequenceEffects(nMainSequenceNodeCount);
+}
+
+
+
+
+void EffectRewinder::skipSomeMainSequenceEffects (sal_Int32 nSkipCount)
+{
+ while (--nSkipCount >= 0)
+ skipSingleMainSequenceEffects();
+}
+
+
+
+
+void EffectRewinder::skipSingleMainSequenceEffects (void)
+{
+ // This basically just starts the next effect and then skips over its
+ // animation.
+ mrEventMultiplexer.notifyNextEffect();
+ mrEventQueue.forceEmpty();
+ mrUserEventQueue.callSkipEffectEventHandler();
+ mrEventQueue.forceEmpty();
+}
+
+
+
+
+bool EffectRewinder::resetEffectCount (void)
+{
+ mnMainSequenceEffectCount = 0;
+ return false;
+}
+
+
+
+
+bool EffectRewinder::notifyAnimationStart (const AnimationNodeSharedPtr& rpNode)
+{
+ // This notification is only relevant for us when the rpNode belongs to
+ // the main sequence.
+ BaseNodeSharedPtr pBaseNode (::boost::dynamic_pointer_cast<BaseNode>(rpNode));
+ if ( ! pBaseNode)
+ return false;
+
+ BaseContainerNodeSharedPtr pParent (pBaseNode->getParentNode());
+ if ( ! (pParent && pParent->isMainSequenceRootNode()))
+ return false;
+
+ // This notification is only relevant for us when the effect is user
+ // triggered.
+ bool bIsUserTriggered (false);
+
+ Reference<animations::XAnimationNode> xNode (rpNode->getXAnimationNode());
+ if (xNode.is())
+ {
+ animations::Event aEvent;
+ if ((xNode->getBegin() >>= aEvent))
+ bIsUserTriggered = (aEvent.Trigger == animations::EventTrigger::ON_NEXT);
+ }
+
+ if (bIsUserTriggered)
+ ++mnMainSequenceEffectCount;
+ else
+ mbNonUserTriggeredMainSequenceEffectSeen = true;
+
+ return false;
+}
+
+
+
+
+void EffectRewinder::asynchronousRewind (
+ sal_Int32 nEffectCount,
+ const bool bRedisplayCurrentSlide,
+ const boost::function<void(void)>& rSlideRewindFunctor)
+{
+ OSL_ASSERT(mpAsynchronousRewindEvent);
+
+ if (bRedisplayCurrentSlide)
+ {
+ mpPaintLock->Activate();
+ // Re-display the current slide.
+ if (rSlideRewindFunctor)
+ rSlideRewindFunctor();
+ mpAsynchronousRewindEvent = makeEvent(
+ ::boost::bind(
+ &EffectRewinder::asynchronousRewind,
+ this,
+ nEffectCount,
+ false,
+ rSlideRewindFunctor),
+ "EffectRewinder::asynchronousRewind");
+ mrEventQueue.addEvent(mpAsynchronousRewindEvent);
+ }
+ else
+ {
+ // Process initial events and skip any animations that are started
+ // when the slide is shown.
+ mbNonUserTriggeredMainSequenceEffectSeen = false;
+ mrEventQueue.forceEmpty();
+ if (mbNonUserTriggeredMainSequenceEffectSeen)
+ {
+ mrUserEventQueue.callSkipEffectEventHandler();
+ mrEventQueue.forceEmpty();
+ }
+
+ while (--nEffectCount >= 0)
+ skipSingleMainSequenceEffects();
+
+ mpAsynchronousRewindEvent.reset();
+ mpPaintLock.reset();
+ }
+}
+
+
+
+
+void EffectRewinder::asynchronousRewindToPreviousSlide (
+ const ::boost::function<void(void)>& rSlideRewindFunctor)
+{
+ OSL_ASSERT(mpAsynchronousRewindEvent);
+
+ mpAsynchronousRewindEvent.reset();
+ rSlideRewindFunctor();
+}
+
+
+
+
+} } // end of namespace ::slideshow::internal
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/effectrewinder.hxx b/slideshow/source/engine/effectrewinder.hxx
new file mode 100644
index 000000000000..d61b559c6a9f
--- /dev/null
+++ b/slideshow/source/engine/effectrewinder.hxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EFFECT_REWINDER_HXX
+#define INCLUDED_SLIDESHOW_EFFECT_REWINDER_HXX
+
+#include "animationnode.hxx"
+#include "eventhandler.hxx"
+#include "animationeventhandler.hxx"
+#include "event.hxx"
+#include "screenupdater.hxx"
+
+#include <com/sun/star/presentation/XSlideShow.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
+#include <vector>
+
+namespace css = ::com::sun::star;
+
+namespace slideshow { namespace internal {
+
+class EventMultiplexer;
+class EventQueue;
+class UserEventQueue;
+
+/** Rewind single effects of the main effect sequence. A rewind is
+ initiated by calling the Rewind() method. Part of the processing is
+ done asynchronously. Multiple EventQueue::update() calls may be
+ necessary to finish a rewind.
+
+ Remember to call SetRootAnimationNode() when switching to a different
+ slide so that the EffectRewinder can determine the number of main
+ sequence effects.
+*/
+class EffectRewinder
+{
+public:
+ EffectRewinder (
+ EventMultiplexer& rEventMultiplexer,
+ EventQueue& rEventQueue,
+ UserEventQueue& rUserEventQueue);
+ ~EffectRewinder (void);
+
+ /** Call Dispose() before the ownder of an EffectRewinder object dies so
+ that the EffectRewinder can release all references to the owner.
+
+ */
+ void dispose (void);
+
+ /** Store the root node of the animation tree. It is used in
+ CountMainSequenceEffects() to count the number of main sequence
+ effects (or effect groups.)
+ */
+ void setRootAnimationNode (
+ const css::uno::Reference<css::animations::XAnimationNode>& xRootNode);
+
+ /** Rewind one effect of the main effect sequence. When the current
+ slide has not effects or no main sequence effect has yet been played
+ then switch to the previous slide and replay all of its main
+ sequence effects.
+ The caller has to pass two functors that redisplay the current slide
+ or switch to the previous slide so that it does not have to expose
+ its internals to us. Only one of the two functors is called.
+ @param rpPaintLock
+ This paint lock is released after the whole asynchronous
+ procoess of rewinding the current effect is completed. It
+ prevents intermediate repaints that would show partial replay
+ of effects.
+ @param rSlideRewindFunctor
+ This functor is called when the current slide is to be
+ redisplayed. When it is called then the other functor is not
+ called.
+ @param rPreviousSlideFunctor
+ This functor is called to switch to the previous slide. When it
+ is called then the other functor is not called.
+ */
+ bool rewind (
+ const ::boost::shared_ptr<ScreenUpdater::UpdateLock>& rpPaintLock,
+ const ::boost::function<void(void)>& rSlideRewindFunctor,
+ const ::boost::function<void(void)>& rPreviousSlideFunctor);
+
+ /** Call this method after gotoPreviousEffect() triggered a slide change
+ to the previous slide.
+ */
+ void skipAllMainSequenceEffects (void);
+
+private:
+ EventMultiplexer& mrEventMultiplexer;
+ EventQueue& mrEventQueue;
+ UserEventQueue& mrUserEventQueue;
+
+ EventHandlerSharedPtr mpSlideStartHandler;
+ EventHandlerSharedPtr mpSlideEndHandler;
+ AnimationEventHandlerSharedPtr mpAnimationStartHandler;
+
+ /** The number off main sequence effects so far.
+ */
+ sal_Int32 mnMainSequenceEffectCount;
+
+ /** This is the currently scheduled event that executes the asynchronous
+ part of the effect rewinding. It is also used as flag that prevents
+ nested rewinds.
+ */
+ EventSharedPtr mpAsynchronousRewindEvent;
+
+ css::uno::Reference<css::animations::XAnimationNode> mxCurrentAnimationRootNode;
+ ::boost::shared_ptr<ScreenUpdater::UpdateLock> mpPaintLock;
+
+ bool mbNonUserTriggeredMainSequenceEffectSeen;
+
+ void initialize (void);
+
+ bool resetEffectCount (void);
+ /** Called by listeners when an animation (not necessarily of a main
+ sequence effect) starts.
+ */
+ bool notifyAnimationStart (const AnimationNodeSharedPtr& rpNode);
+
+ /** Count the number of effects (or effect groups) in the main effect
+ sequence.
+ */
+ sal_Int32 countMainSequenceEffects (void);
+
+ /** Skip the next main sequence effect.
+ */
+ void skipSingleMainSequenceEffects (void);
+
+ /** Skip the specified number of main sequence effects.
+ */
+ void skipSomeMainSequenceEffects (const sal_Int32 nSkipCount);
+
+ /** Rewind the last effect of the main effect sequence by replaying all
+ previous effects.
+ @param nEffectCount
+ The number of main sequence effects to replay.
+ @param bRedisplayCurrentSlide
+ When <TRUE/> then the current slide is redisplayed before the
+ effects are replayed.
+ @param rSlideRewindFunctor
+ This functor is used to redisplay the current slide.
+ */
+ void asynchronousRewind (
+ sal_Int32 nEffectCount,
+ const bool bRedisplayCurrentSlide,
+ const boost::function<void(void)>& rSlideRewindFunctor);
+
+ /** Go to the previous slide and replay all of its main sequence effects
+ (or effect groups).
+ @param rPreviousSlideFunctor
+ This functor is used to go to the previous slide.
+ */
+ void asynchronousRewindToPreviousSlide (
+ const ::boost::function<void(void)>& rPreviousSlideFunctor);
+};
+
+} } // end of namespace ::slideshow::internal
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/eventmultiplexer.cxx b/slideshow/source/engine/eventmultiplexer.cxx
new file mode 100644
index 000000000000..4f5ecd4f8a03
--- /dev/null
+++ b/slideshow/source/engine/eventmultiplexer.cxx
@@ -0,0 +1,1280 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/ref.hxx>
+#include <cppuhelper/compbase2.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+#include <com/sun/star/awt/XMouseListener.hpp>
+#include <com/sun/star/awt/XMouseMotionListener.hpp>
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/presentation/XSlideShowView.hpp>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "tools.hxx"
+#include "eventqueue.hxx"
+#include "eventmultiplexer.hxx"
+#include "listenercontainer.hxx"
+#include "delayevent.hxx"
+#include "unoview.hxx"
+#include "unoviewcontainer.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/bind.hpp>
+
+#include <vector>
+#include <hash_map>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+namespace boost
+{
+ // add operator== for weak_ptr
+ template<typename T> bool operator==( weak_ptr<T> const& rLHS,
+ weak_ptr<T> const& rRHS )
+ {
+ return !(rLHS<rRHS) && !(rRHS<rLHS);
+ }
+}
+
+namespace slideshow {
+namespace internal {
+
+template <typename HandlerT>
+class PrioritizedHandlerEntry
+{
+ typedef boost::shared_ptr<HandlerT> HandlerSharedPtrT;
+ HandlerSharedPtrT mpHandler;
+ double mnPrio;
+
+public:
+ PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler,
+ double nPrio ) :
+ mpHandler(pHandler),
+ mnPrio(nPrio)
+ {}
+
+ HandlerSharedPtrT const& getHandler() const { return mpHandler; }
+
+ /// To sort according to priority
+ bool operator<( PrioritizedHandlerEntry const& rRHS ) const
+ {
+ // reversed order - high prioritized entries
+ // should be at the beginning of the queue
+ return mnPrio > rRHS.mnPrio;
+ }
+
+ /// To permit std::remove in removeHandler template
+ bool operator==( PrioritizedHandlerEntry const& rRHS ) const
+ {
+ // ignore prio, for removal, only the handler ptr matters
+ return mpHandler == rRHS.mpHandler;
+ }
+};
+
+template<typename T> inline T* get_pointer(PrioritizedHandlerEntry<T> const& handler)
+{
+ return handler.getHandler().get();
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+typedef cppu::WeakComponentImplHelper2<
+ awt::XMouseListener,
+ awt::XMouseMotionListener > Listener_UnoBase;
+
+/** Listener class, to decouple UNO lifetime from EventMultiplexer
+
+ This class gets registered as the XMouse(Motion)Listener on the
+ XSlideViews, and passes on the events to the EventMultiplexer (via
+ EventQueue indirection, to force the events into the main thread)
+ */
+class EventMultiplexerListener : private cppu::BaseMutex,
+ public Listener_UnoBase,
+ private ::boost::noncopyable
+{
+public:
+ EventMultiplexerListener( EventQueue& rEventQueue,
+ EventMultiplexerImpl& rEventMultiplexer ) :
+ Listener_UnoBase( m_aMutex ),
+ mpEventQueue( &rEventQueue ),
+ mpEventMultiplexer( &rEventMultiplexer )
+ {
+ }
+
+ // WeakComponentImplHelperBase::disposing
+ virtual void SAL_CALL disposing();
+
+private:
+ virtual void SAL_CALL disposing( const lang::EventObject& Source )
+ throw (uno::RuntimeException);
+
+ // XMouseListener implementation
+ virtual void SAL_CALL mousePressed( const awt::MouseEvent& e )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL mouseExited( const awt::MouseEvent& e )
+ throw (uno::RuntimeException);
+
+ // XMouseMotionListener implementation
+ virtual void SAL_CALL mouseDragged( const awt::MouseEvent& e )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL mouseMoved( const awt::MouseEvent& e )
+ throw (uno::RuntimeException);
+
+
+ EventQueue* mpEventQueue;
+ EventMultiplexerImpl* mpEventMultiplexer;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+struct EventMultiplexerImpl
+{
+ EventMultiplexerImpl( EventQueue& rEventQueue,
+ UnoViewContainer const& rViewContainer ) :
+ mrEventQueue(rEventQueue),
+ mrViewContainer(rViewContainer),
+ mxListener( new EventMultiplexerListener(rEventQueue,
+ *this) ),
+ maNextEffectHandlers(),
+ maSlideStartHandlers(),
+ maSlideEndHandlers(),
+ maAnimationStartHandlers(),
+ maAnimationEndHandlers(),
+ maSlideAnimationsEndHandlers(),
+ maAudioStoppedHandlers(),
+ maCommandStopAudioHandlers(),
+ maPauseHandlers(),
+ maViewHandlers(),
+ maViewRepaintHandlers(),
+ maShapeListenerHandlers(),
+ maUserPaintEventHandlers(),
+ maShapeCursorHandlers(),
+ maMouseClickHandlers(),
+ maMouseDoubleClickHandlers(),
+ maMouseMoveHandlers(),
+ maHyperlinkHandlers(),
+ mnTimeout(0.0),
+ mpTickEvent(),
+ mbIsAutoMode(false)
+ {}
+
+ ~EventMultiplexerImpl()
+ {
+ if( mxListener.is() )
+ mxListener->dispose();
+ }
+
+ /// Remove all handlers
+ void clear();
+
+ // actual handler callbacks (get called from the UNO interface
+ // listeners via event queue)
+ void mousePressed( const awt::MouseEvent& e );
+ void mouseReleased( const awt::MouseEvent& e );
+ void mouseDragged( const awt::MouseEvent& e );
+ void mouseMoved( const awt::MouseEvent& e );
+
+ bool isMouseListenerRegistered() const;
+
+ typedef ThreadUnsafeListenerContainer<
+ PrioritizedHandlerEntry<EventHandler>,
+ std::vector<
+ PrioritizedHandlerEntry<EventHandler> > > ImplNextEffectHandlers;
+ typedef PrioritizedHandlerEntry<MouseEventHandler> ImplMouseHandlerEntry;
+ typedef ThreadUnsafeListenerContainer<
+ ImplMouseHandlerEntry,
+ std::vector<ImplMouseHandlerEntry> > ImplMouseHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ EventHandlerSharedPtr,
+ std::vector<EventHandlerSharedPtr> > ImplEventHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ AnimationEventHandlerSharedPtr,
+ std::vector<AnimationEventHandlerSharedPtr> > ImplAnimationHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ PauseEventHandlerSharedPtr,
+ std::vector<PauseEventHandlerSharedPtr> > ImplPauseHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ ViewEventHandlerWeakPtr,
+ std::vector<ViewEventHandlerWeakPtr> > ImplViewHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ ViewRepaintHandlerSharedPtr,
+ std::vector<ViewRepaintHandlerSharedPtr> > ImplRepaintHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ ShapeListenerEventHandlerSharedPtr,
+ std::vector<ShapeListenerEventHandlerSharedPtr> > ImplShapeListenerHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ UserPaintEventHandlerSharedPtr,
+ std::vector<UserPaintEventHandlerSharedPtr> > ImplUserPaintEventHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ ShapeCursorEventHandlerSharedPtr,
+ std::vector<ShapeCursorEventHandlerSharedPtr> > ImplShapeCursorHandlers;
+ typedef ThreadUnsafeListenerContainer<
+ PrioritizedHandlerEntry<HyperlinkHandler>,
+ std::vector<PrioritizedHandlerEntry<HyperlinkHandler> > > ImplHyperLinkHandlers;
+
+ template <typename XSlideShowViewFunc>
+ void forEachView( XSlideShowViewFunc pViewMethod );
+
+ UnoViewSharedPtr findUnoView(const uno::Reference<
+ presentation::XSlideShowView>& xView) const;
+
+ template< typename RegisterFunction >
+ void addMouseHandler( ImplMouseHandlers& rHandlerContainer,
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority,
+ RegisterFunction pRegisterListener );
+
+ bool notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
+ AnimationNodeSharedPtr const& rNode );
+
+ bool notifyMouseHandlers(
+ const ImplMouseHandlers& rQueue,
+ bool (MouseEventHandler::*pHandlerMethod)(
+ const awt::MouseEvent& ),
+ const awt::MouseEvent& e );
+
+ bool notifyNextEffect();
+
+ /// Called for automatic nextEffect
+ void tick();
+
+ /// Schedules a tick event
+ void scheduleTick();
+
+ /// Schedules tick events, if mbIsAutoMode is true
+ void handleTicks();
+
+
+ EventQueue& mrEventQueue;
+ UnoViewContainer const& mrViewContainer;
+ ::rtl::Reference<
+ EventMultiplexerListener> mxListener;
+
+ ImplNextEffectHandlers maNextEffectHandlers;
+ ImplEventHandlers maSlideStartHandlers;
+ ImplEventHandlers maSlideEndHandlers;
+ ImplAnimationHandlers maAnimationStartHandlers;
+ ImplAnimationHandlers maAnimationEndHandlers;
+ ImplEventHandlers maSlideAnimationsEndHandlers;
+ ImplAnimationHandlers maAudioStoppedHandlers;
+ ImplAnimationHandlers maCommandStopAudioHandlers;
+ ImplPauseHandlers maPauseHandlers;
+ ImplViewHandlers maViewHandlers;
+ ImplRepaintHandlers maViewRepaintHandlers;
+ ImplShapeListenerHandlers maShapeListenerHandlers;
+ ImplUserPaintEventHandlers maUserPaintEventHandlers;
+ ImplShapeCursorHandlers maShapeCursorHandlers;
+ ImplMouseHandlers maMouseClickHandlers;
+ ImplMouseHandlers maMouseDoubleClickHandlers;
+ ImplMouseHandlers maMouseMoveHandlers;
+ ImplHyperLinkHandlers maHyperlinkHandlers;
+
+ /// automatic next effect mode timeout
+ double mnTimeout;
+
+ /** Holds ptr to optional tick event weakly
+
+ When event queue is cleansed, the next
+ setAutomaticMode(true) call is then able to
+ regenerate the event.
+ */
+ ::boost::weak_ptr< Event > mpTickEvent;
+ bool mbIsAutoMode;
+};
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+void SAL_CALL EventMultiplexerListener::disposing()
+{
+ osl::MutexGuard const guard( m_aMutex );
+ mpEventQueue = NULL;
+ mpEventMultiplexer = NULL;
+}
+
+void SAL_CALL EventMultiplexerListener::disposing(
+ const lang::EventObject& /*rSource*/ ) throw (uno::RuntimeException)
+{
+ // there's no real point in acting on this message - after all,
+ // the event sources are the XSlideShowViews, which must be
+ // explicitely removed from the slideshow via
+ // XSlideShow::removeView(). thus, if a XSlideShowView has
+ // properly removed itself from the slideshow, it will not be
+ // found here. and if it hasn't, there'll be other references at
+ // other places within the slideshow, anyway...
+}
+
+void SAL_CALL EventMultiplexerListener::mousePressed(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // notify mouse press. Don't call handlers directly, this
+ // might not be the main thread!
+ if( mpEventQueue )
+ mpEventQueue->addEvent(
+ makeEvent( boost::bind( &EventMultiplexerImpl::mousePressed,
+ mpEventMultiplexer,
+ e ),
+ "EventMultiplexerImpl::mousePressed") );
+}
+
+void SAL_CALL EventMultiplexerListener::mouseReleased(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // notify mouse release. Don't call handlers directly,
+ // this might not be the main thread!
+ if( mpEventQueue )
+ mpEventQueue->addEvent(
+ makeEvent( boost::bind( &EventMultiplexerImpl::mouseReleased,
+ mpEventMultiplexer,
+ e ),
+ "EventMultiplexerImpl::mouseReleased") );
+}
+
+void SAL_CALL EventMultiplexerListener::mouseEntered(
+ const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException)
+{
+ // not used here
+}
+
+void SAL_CALL EventMultiplexerListener::mouseExited(
+ const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException)
+{
+ // not used here
+}
+
+// XMouseMotionListener implementation
+void SAL_CALL EventMultiplexerListener::mouseDragged(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // notify mouse drag. Don't call handlers directly, this
+ // might not be the main thread!
+ if( mpEventQueue )
+ mpEventQueue->addEvent(
+ makeEvent( boost::bind( &EventMultiplexerImpl::mouseDragged,
+ mpEventMultiplexer,
+ e ),
+ "EventMultiplexerImpl::mouseDragged") );
+}
+
+void SAL_CALL EventMultiplexerListener::mouseMoved(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // notify mouse move. Don't call handlers directly, this
+ // might not be the main thread!
+ if( mpEventQueue )
+ mpEventQueue->addEvent(
+ makeEvent( boost::bind( &EventMultiplexerImpl::mouseMoved,
+ mpEventMultiplexer,
+ e ),
+ "EventMultiplexerImpl::mouseMoved") );
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
+ AnimationNodeSharedPtr const& rNode )
+{
+ return rContainer.applyAll(
+ boost::bind( &AnimationEventHandler::handleAnimationEvent,
+ _1, boost::cref(rNode) ) );
+}
+
+template <typename XSlideShowViewFunc>
+void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod )
+{
+ if( pViewMethod )
+ {
+ // (un)register mouse listener on all views
+ for( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ),
+ aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter )
+ {
+ uno::Reference<presentation::XSlideShowView> xView ((*aIter)->getUnoView());
+ if (xView.is())
+ {
+ (xView.get()->*pViewMethod)( mxListener.get() );
+ }
+ else
+ {
+ OSL_ASSERT(xView.is());
+ }
+ }
+ }
+}
+
+UnoViewSharedPtr EventMultiplexerImpl::findUnoView(
+ const uno::Reference<presentation::XSlideShowView>& xView) const
+{
+ // find view from which the change originated
+ UnoViewVector::const_iterator aIter;
+ const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
+ if( (aIter=std::find_if( mrViewContainer.begin(),
+ aEnd,
+ boost::bind(
+ std::equal_to<uno::Reference<presentation::XSlideShowView> >(),
+ boost::cref( xView ),
+ boost::bind( &UnoView::getUnoView, _1 )))) == aEnd )
+ {
+ OSL_ENSURE(false, "EventMultiplexer::findUnoView(): unexpected message source" );
+ return UnoViewSharedPtr();
+ }
+
+ return *aIter;
+}
+
+template< typename RegisterFunction >
+void EventMultiplexerImpl::addMouseHandler(
+ ImplMouseHandlers& rHandlerContainer,
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority,
+ RegisterFunction pRegisterListener )
+{
+ ENSURE_OR_THROW(
+ rHandler,
+ "EventMultiplexer::addMouseHandler(): Invalid handler" );
+
+ // register mouse listener on all views
+ forEachView( pRegisterListener );
+
+ // add into sorted container:
+ rHandlerContainer.addSorted(
+ typename ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ nPriority ));
+}
+
+bool EventMultiplexerImpl::isMouseListenerRegistered() const
+{
+ return !(maMouseClickHandlers.isEmpty() &&
+ maMouseDoubleClickHandlers.isEmpty());
+}
+
+void EventMultiplexerImpl::tick()
+{
+ if( !mbIsAutoMode )
+ return; // this event is just a left-over, ignore
+
+ notifyNextEffect();
+
+ if( !maNextEffectHandlers.isEmpty() )
+ {
+ // still handlers left, schedule next timeout
+ // event. Will also set mbIsTickEventOn back to true
+ scheduleTick();
+ }
+}
+
+void EventMultiplexerImpl::scheduleTick()
+{
+ EventSharedPtr pEvent(
+ makeDelay( boost::bind( &EventMultiplexerImpl::tick,
+ this ),
+ mnTimeout,
+ "EventMultiplexerImpl::tick with delay"));
+
+ // store weak reference to generated event, to notice when
+ // the event queue gets cleansed (we then have to
+ // regenerate the tick event!)
+ mpTickEvent = pEvent;
+
+ // enabled auto mode: simply schedule a timeout event,
+ // which will eventually call our tick() method
+ mrEventQueue.addEventForNextRound( pEvent );
+}
+
+void EventMultiplexerImpl::handleTicks()
+{
+ if( !mbIsAutoMode )
+ return; // nothing to do, don't need no ticks
+
+ EventSharedPtr pTickEvent( mpTickEvent.lock() );
+ if( pTickEvent )
+ return; // nothing to do, there's already a tick
+ // pending
+
+ // schedule initial tick (which reschedules itself
+ // after that, all by itself)
+ scheduleTick();
+}
+
+
+void EventMultiplexerImpl::clear()
+{
+ // deregister from all views.
+ if( isMouseListenerRegistered() )
+ {
+ for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
+ aEnd=mrViewContainer.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ if( (*aIter)->getUnoView().is() )
+ (*aIter)->getUnoView()->removeMouseListener( mxListener.get() );
+ }
+ }
+
+ if( !maMouseMoveHandlers.isEmpty() )
+ {
+ for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
+ aEnd=mrViewContainer.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ if( (*aIter)->getUnoView().is() )
+ (*aIter)->getUnoView()->removeMouseMotionListener( mxListener.get() );
+ }
+ }
+
+ // clear all handlers (releases all references)
+ maNextEffectHandlers.clear();
+ maSlideStartHandlers.clear();
+ maSlideEndHandlers.clear();
+ maAnimationStartHandlers.clear();
+ maAnimationEndHandlers.clear();
+ maSlideAnimationsEndHandlers.clear();
+ maAudioStoppedHandlers.clear();
+ maCommandStopAudioHandlers.clear();
+ maPauseHandlers.clear();
+ maViewHandlers.clear();
+ maViewRepaintHandlers.clear();
+ maMouseClickHandlers.clear();
+ maMouseDoubleClickHandlers.clear();
+ maMouseMoveHandlers.clear();
+ maHyperlinkHandlers.clear();
+ mpTickEvent.reset();
+}
+
+// XMouseListener implementation
+bool EventMultiplexerImpl::notifyMouseHandlers(
+ const ImplMouseHandlers& rQueue,
+ bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ),
+ const awt::MouseEvent& e )
+{
+ uno::Reference<presentation::XSlideShowView> xView(
+ e.Source, uno::UNO_QUERY );
+
+ ENSURE_OR_RETURN_FALSE( xView.is(), "EventMultiplexer::notifyHandlers(): "
+ "event source is not an XSlideShowView" );
+
+ // find corresponding view (to map mouse position into user
+ // coordinate space)
+ UnoViewVector::const_iterator aIter;
+ const UnoViewVector::const_iterator aBegin( mrViewContainer.begin() );
+ const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() );
+ if( (aIter=::std::find_if(
+ aBegin, aEnd,
+ boost::bind( std::equal_to< uno::Reference<
+ presentation::XSlideShowView > >(),
+ boost::cref( xView ),
+ boost::bind( &UnoView::getUnoView, _1 ) ) ) ) == aEnd)
+ {
+ ENSURE_OR_RETURN_FALSE(
+ false, "EventMultiplexer::notifyHandlers(): "
+ "event source not found under registered views" );
+ }
+
+ // convert mouse position to user coordinate space
+ ::basegfx::B2DPoint aPosition( e.X, e.Y );
+ ::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() );
+ if( !aMatrix.invert() )
+ ENSURE_OR_THROW( false, "EventMultiplexer::notifyHandlers():"
+ " view matrix singular" );
+ aPosition *= aMatrix;
+
+ awt::MouseEvent aEvent( e );
+ aEvent.X = ::basegfx::fround( aPosition.getX() );
+ aEvent.Y = ::basegfx::fround( aPosition.getY() );
+
+ // fire event on handlers, try in order of precedence. If
+ // one high-priority handler rejects the event
+ // (i.e. returns false), try next handler.
+ return rQueue.apply(
+ boost::bind(
+ pHandlerMethod,
+ boost::bind(
+ &ImplMouseHandlers::container_type::value_type::getHandler,
+ _1 ),
+ aEvent ));
+}
+
+void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e )
+{
+ // fire double-click events for every second click
+ sal_Int32 nCurrClickCount = e.ClickCount;
+ while( nCurrClickCount > 1 &&
+ notifyMouseHandlers( maMouseDoubleClickHandlers,
+ &MouseEventHandler::handleMousePressed,
+ e ))
+ {
+ nCurrClickCount -= 2;
+ }
+
+ // fire single-click events for all remaining clicks
+ while( nCurrClickCount > 0 &&
+ notifyMouseHandlers( maMouseClickHandlers,
+ &MouseEventHandler::handleMousePressed,
+ e ))
+ {
+ --nCurrClickCount;
+ }
+}
+
+void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e )
+{
+ // fire double-click events for every second click
+ sal_Int32 nCurrClickCount = e.ClickCount;
+ while( nCurrClickCount > 1 &&
+ notifyMouseHandlers( maMouseDoubleClickHandlers,
+ &MouseEventHandler::handleMouseReleased,
+ e ))
+ {
+ nCurrClickCount -= 2;
+ }
+
+ // fire single-click events for all remaining clicks
+ while( nCurrClickCount > 0 &&
+ notifyMouseHandlers( maMouseClickHandlers,
+ &MouseEventHandler::handleMouseReleased,
+ e ))
+ {
+ --nCurrClickCount;
+ }
+}
+
+void EventMultiplexerImpl::mouseDragged( const awt::MouseEvent& e )
+{
+ notifyMouseHandlers( maMouseMoveHandlers,
+ &MouseEventHandler::handleMouseDragged,
+ e );
+}
+
+void EventMultiplexerImpl::mouseMoved( const awt::MouseEvent& e )
+{
+ notifyMouseHandlers( maMouseMoveHandlers,
+ &MouseEventHandler::handleMouseMoved,
+ e );
+}
+
+bool EventMultiplexerImpl::notifyNextEffect()
+{
+ // fire event on handlers, try in order of precedence. If one
+ // high-priority handler rejects the event (i.e. returns false),
+ // try next handler.
+ return maNextEffectHandlers.apply(
+ boost::bind(
+ &EventHandler::handleEvent,
+ boost::bind(
+ &ImplNextEffectHandlers::container_type::value_type::getHandler,
+ _1 )) );
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+
+EventMultiplexer::EventMultiplexer( EventQueue& rEventQueue,
+ UnoViewContainer const& rViewContainer ) :
+ mpImpl( new EventMultiplexerImpl(rEventQueue, rViewContainer) )
+{
+}
+
+EventMultiplexer::~EventMultiplexer()
+{
+ // outline because of EventMultiplexerImpl's incomplete type
+}
+
+void EventMultiplexer::clear()
+{
+ mpImpl->clear();
+}
+
+void EventMultiplexer::setAutomaticMode( bool bIsAuto )
+{
+ if( bIsAuto == mpImpl->mbIsAutoMode )
+ return; // no change, nothing to do
+
+ mpImpl->mbIsAutoMode = bIsAuto;
+
+ mpImpl->handleTicks();
+}
+
+bool EventMultiplexer::getAutomaticMode() const
+{
+ return mpImpl->mbIsAutoMode;
+}
+
+void EventMultiplexer::setAutomaticTimeout( double nTimeout )
+{
+ mpImpl->mnTimeout = nTimeout;
+}
+
+double EventMultiplexer::getAutomaticTimeout() const
+{
+ return mpImpl->mnTimeout;
+}
+
+void EventMultiplexer::addNextEffectHandler(
+ EventHandlerSharedPtr const& rHandler,
+ double nPriority )
+{
+ mpImpl->maNextEffectHandlers.addSorted(
+ EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
+ rHandler,
+ nPriority) );
+
+ // Enable tick events, if not done already
+ mpImpl->handleTicks();
+}
+
+void EventMultiplexer::removeNextEffectHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maNextEffectHandlers.remove(
+ EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+}
+
+void EventMultiplexer::addSlideStartHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideStartHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeSlideStartHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideStartHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addSlideEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideEndHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeSlideEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideEndHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addAnimationStartHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationStartHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeAnimationStartHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationStartHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addAnimationEndHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationEndHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeAnimationEndHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationEndHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addSlideAnimationsEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideAnimationsEndHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeSlideAnimationsEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideAnimationsEndHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addAudioStoppedHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAudioStoppedHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeAudioStoppedHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAudioStoppedHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addCommandStopAudioHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maCommandStopAudioHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeCommandStopAudioHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maCommandStopAudioHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addPauseHandler(
+ const PauseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maPauseHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removePauseHandler(
+ const PauseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maPauseHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addViewHandler(
+ const ViewEventHandlerWeakPtr& rHandler )
+{
+ mpImpl->maViewHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeViewHandler( const ViewEventHandlerWeakPtr& rHandler )
+{
+ mpImpl->maViewHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
+{
+ mpImpl->maViewRepaintHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler )
+{
+ mpImpl->maViewRepaintHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maShapeListenerHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maShapeListenerHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maUserPaintEventHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maUserPaintEventHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maShapeCursorHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maShapeCursorHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority )
+{
+ mpImpl->addMouseHandler(
+ mpImpl->maMouseClickHandlers,
+ rHandler,
+ nPriority,
+ mpImpl->isMouseListenerRegistered()
+ ? NULL
+ : &presentation::XSlideShowView::addMouseListener );
+}
+
+void EventMultiplexer::removeClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maMouseClickHandlers.remove(
+ EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+
+ if( !mpImpl->isMouseListenerRegistered() )
+ mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
+}
+
+void EventMultiplexer::addDoubleClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority )
+{
+ mpImpl->addMouseHandler(
+ mpImpl->maMouseDoubleClickHandlers,
+ rHandler,
+ nPriority,
+ mpImpl->isMouseListenerRegistered()
+ ? NULL
+ : &presentation::XSlideShowView::addMouseListener );
+}
+
+void EventMultiplexer::removeDoubleClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maMouseDoubleClickHandlers.remove(
+ EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+
+ if( !mpImpl->isMouseListenerRegistered() )
+ mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
+}
+
+void EventMultiplexer::addMouseMoveHandler(
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority )
+{
+ mpImpl->addMouseHandler(
+ mpImpl->maMouseMoveHandlers,
+ rHandler,
+ nPriority,
+ mpImpl->maMouseMoveHandlers.isEmpty()
+ ? &presentation::XSlideShowView::addMouseMotionListener
+ : NULL );
+}
+
+void EventMultiplexer::removeMouseMoveHandler(
+ const MouseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maMouseMoveHandlers.remove(
+ EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+
+ if( mpImpl->maMouseMoveHandlers.isEmpty() )
+ mpImpl->forEachView(
+ &presentation::XSlideShowView::removeMouseMotionListener );
+}
+
+void EventMultiplexer::addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler,
+ double nPriority )
+{
+ mpImpl->maHyperlinkHandlers.addSorted(
+ EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
+ rHandler,
+ nPriority) );
+}
+
+void EventMultiplexer::removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler )
+{
+ mpImpl->maHyperlinkHandlers.remove(
+ EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+}
+
+bool EventMultiplexer::notifyShapeListenerAdded(
+ const uno::Reference<presentation::XShapeEventListener>& xListener,
+ const uno::Reference<drawing::XShape>& xShape )
+{
+ return mpImpl->maShapeListenerHandlers.applyAll(
+ boost::bind(&ShapeListenerEventHandler::listenerAdded,
+ _1,
+ boost::cref(xListener),
+ boost::cref(xShape)) );
+}
+
+bool EventMultiplexer::notifyShapeListenerRemoved(
+ const uno::Reference<presentation::XShapeEventListener>& xListener,
+ const uno::Reference<drawing::XShape>& xShape )
+{
+ return mpImpl->maShapeListenerHandlers.applyAll(
+ boost::bind(&ShapeListenerEventHandler::listenerRemoved,
+ _1,
+ boost::cref(xListener),
+ boost::cref(xShape)) );
+}
+
+bool EventMultiplexer::notifyShapeCursorChange(
+ const uno::Reference<drawing::XShape>& xShape,
+ sal_Int16 nPointerShape )
+{
+ return mpImpl->maShapeCursorHandlers.applyAll(
+ boost::bind(&ShapeCursorEventHandler::cursorChanged,
+ _1,
+ boost::cref(xShape),
+ nPointerShape));
+}
+
+bool EventMultiplexer::notifyUserPaintColor( RGBColor const& rUserColor )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::colorChanged,
+ _1,
+ boost::cref(rUserColor)));
+}
+
+bool EventMultiplexer::notifyUserPaintStrokeWidth( double rUserStrokeWidth )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::widthChanged,
+ _1,
+ rUserStrokeWidth));
+}
+
+bool EventMultiplexer::notifyUserPaintDisabled()
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::mem_fn(&UserPaintEventHandler::disable));
+}
+
+bool EventMultiplexer::notifySwitchPenMode(){
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::mem_fn(&UserPaintEventHandler::switchPenMode));
+}
+
+bool EventMultiplexer::notifySwitchEraserMode(){
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::mem_fn(&UserPaintEventHandler::switchEraserMode));
+}
+
+//adding erasing all ink features with UserPaintOverlay
+bool EventMultiplexer::notifyEraseAllInk( bool const& rEraseAllInk )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::eraseAllInkChanged,
+ _1,
+ boost::cref(rEraseAllInk)));
+}
+
+//adding erasing features with UserPaintOverlay
+bool EventMultiplexer::notifyEraseInkWidth( sal_Int32 rEraseInkSize )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::eraseInkWidthChanged,
+ _1,
+ boost::cref(rEraseInkSize)));
+}
+
+bool EventMultiplexer::notifyNextEffect()
+{
+ return mpImpl->notifyNextEffect();
+}
+
+bool EventMultiplexer::notifySlideStartEvent()
+{
+ return mpImpl->maSlideStartHandlers.applyAll(
+ boost::mem_fn(&EventHandler::handleEvent) );
+}
+
+bool EventMultiplexer::notifySlideEndEvent()
+{
+ return mpImpl->maSlideEndHandlers.applyAll(
+ boost::mem_fn(&EventHandler::handleEvent) );
+}
+
+bool EventMultiplexer::notifyAnimationStart(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifyAnimationEnd(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifySlideAnimationsEnd()
+{
+ return mpImpl->maSlideAnimationsEndHandlers.applyAll(
+ boost::mem_fn(&EventHandler::handleEvent));
+}
+
+bool EventMultiplexer::notifyAudioStopped(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers(
+ mpImpl->maAudioStoppedHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifyCommandStopAudio(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers(
+ mpImpl->maCommandStopAudioHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifyPauseMode( bool bPauseShow )
+{
+ return mpImpl->maPauseHandlers.applyAll(
+ boost::bind( &PauseEventHandler::handlePause,
+ _1, bPauseShow ));
+}
+
+bool EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView )
+{
+ ENSURE_OR_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view");
+
+ // register event listener
+ uno::Reference<presentation::XSlideShowView> const rUnoView(
+ rView->getUnoView() );
+
+ if( mpImpl->isMouseListenerRegistered() )
+ rUnoView->addMouseListener(
+ mpImpl->mxListener.get() );
+
+ if( !mpImpl->maMouseMoveHandlers.isEmpty() )
+ rUnoView->addMouseMotionListener(
+ mpImpl->mxListener.get() );
+
+ return mpImpl->maViewHandlers.applyAll(
+ boost::bind( &ViewEventHandler::viewAdded,
+ _1,
+ boost::cref(rView) ));
+}
+
+bool EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView )
+{
+ ENSURE_OR_THROW( rView,
+ "EventMultiplexer::removeView(): Invalid view" );
+
+ // revoke event listeners
+ uno::Reference<presentation::XSlideShowView> const rUnoView(
+ rView->getUnoView() );
+
+ if( mpImpl->isMouseListenerRegistered() )
+ rUnoView->removeMouseListener(
+ mpImpl->mxListener.get() );
+
+ if( !mpImpl->maMouseMoveHandlers.isEmpty() )
+ rUnoView->removeMouseMotionListener(
+ mpImpl->mxListener.get() );
+
+ return mpImpl->maViewHandlers.applyAll(
+ boost::bind( &ViewEventHandler::viewRemoved,
+ _1,
+ boost::cref(rView) ));
+}
+
+bool EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView )
+{
+ return mpImpl->maViewHandlers.applyAll(
+ boost::bind( &ViewEventHandler::viewChanged,
+ _1,
+ boost::cref(rView) ));
+}
+
+bool EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView )
+{
+ UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
+
+ if( !pView )
+ return false; // view not registered here
+
+ return notifyViewChanged( pView );
+}
+
+bool EventMultiplexer::notifyViewsChanged()
+{
+ return mpImpl->maViewHandlers.applyAll(
+ boost::mem_fn( &ViewEventHandler::viewsChanged ));
+}
+
+bool EventMultiplexer::notifyViewClobbered(
+ const uno::Reference<presentation::XSlideShowView>& xView )
+{
+ UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
+
+ if( !pView )
+ return false; // view not registered here
+
+ return mpImpl->maViewRepaintHandlers.applyAll(
+ boost::bind( &ViewRepaintHandler::viewClobbered,
+ _1,
+ boost::cref(pView) ));
+}
+
+bool EventMultiplexer::notifyHyperlinkClicked(
+ rtl::OUString const& hyperLink )
+{
+ return mpImpl->maHyperlinkHandlers.apply(
+ boost::bind(&HyperlinkHandler::handleHyperlink,
+ _1,
+ boost::cref(hyperLink)) );
+}
+
+bool EventMultiplexer::notifySlideTransitionStarted()
+{
+ return true;
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/eventqueue.cxx b/slideshow/source/engine/eventqueue.cxx
new file mode 100644
index 000000000000..2e8cd72eaf3a
--- /dev/null
+++ b/slideshow/source/engine/eventqueue.cxx
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+#include "debug.hxx"
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <event.hxx>
+#include <eventqueue.hxx>
+#include <slideshowexceptions.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <limits>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ bool EventQueue::EventEntry::operator<( const EventEntry& rEvent ) const
+ {
+ // negate comparison, we want priority queue to be sorted
+ // in increasing order of activation times
+ return this->nTime > rEvent.nTime;
+ }
+
+
+ EventQueue::EventQueue(
+ boost::shared_ptr<canvas::tools::ElapsedTime> const & pPresTimer )
+ : maMutex(),
+ maEvents(),
+ maNextEvents(),
+ maNextNextEvents(),
+ mpTimer( pPresTimer )
+ {
+ }
+
+ EventQueue::~EventQueue()
+ {
+ // add in all that have been added explicitly for this round:
+ EventEntryVector::const_iterator const iEnd( maNextEvents.end() );
+ for ( EventEntryVector::const_iterator iPos( maNextEvents.begin() );
+ iPos != iEnd; ++iPos )
+ {
+ maEvents.push(*iPos);
+ }
+ EventEntryVector().swap( maNextEvents );
+
+ // dispose event queue
+ while( !maEvents.empty() )
+ {
+ try
+ {
+ maEvents.top().pEvent->dispose();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ maEvents.pop();
+ }
+ }
+
+ bool EventQueue::addEvent( const EventSharedPtr& rEvent )
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+#if OSL_DEBUG_LEVEL > 1 && defined (SLIDESHOW_ADD_DESCRIPTIONS_TO_EVENTS)
+ OSL_TRACE("adding at %f event [%s] at %x with delay %f\r",
+ mpTimer->getElapsedTime(),
+ OUStringToOString(rEvent->GetDescription(), RTL_TEXTENCODING_UTF8).getStr(),
+ rEvent.get(),
+ rEvent->getActivationTime(0.0));
+#endif
+ ENSURE_OR_RETURN_FALSE( rEvent,
+ "EventQueue::addEvent: event ptr NULL" );
+
+ // prepare entry
+
+ // A seemingly obvious optimization cannot be used here,
+ // because it breaks assumed order of notification: zero
+ // timeout events could be fired() immediately, but that
+ // would not unwind the stack and furthermore changes
+ // order of notification
+
+ // add entry
+ maEvents.push( EventEntry( rEvent, rEvent->getActivationTime(
+ mpTimer->getElapsedTime()) ) );
+ return true;
+ }
+
+ bool EventQueue::addEventForNextRound( EventSharedPtr const& rEvent )
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+#if OSL_DEBUG_LEVEL > 1 && defined (SLIDESHOW_ADD_DESCRIPTIONS_TO_EVENTS)
+ OSL_TRACE("adding at %f event [%s] at %x for next round with delay %f\r",
+ mpTimer->getElapsedTime(),
+ OUStringToOString(rEvent->GetDescription(), RTL_TEXTENCODING_UTF8).getStr(),
+ rEvent.get(),
+ rEvent->getActivationTime(0.0));
+#endif
+
+ ENSURE_OR_RETURN_FALSE( rEvent.get() != NULL,
+ "EventQueue::addEvent: event ptr NULL" );
+ maNextEvents.push_back(
+ EventEntry( rEvent, rEvent->getActivationTime(
+ mpTimer->getElapsedTime()) ) );
+ return true;
+ }
+
+ bool EventQueue::addEventWhenQueueIsEmpty (const EventSharedPtr& rpEvent)
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+#if OSL_DEBUG_LEVEL > 1 && defined (SLIDESHOW_ADD_DESCRIPTIONS_TO_EVENTS)
+ OSL_TRACE("adding at %f event [%s] at %x for execution when queue is empty with delay %f\r",
+ mpTimer->getElapsedTime(),
+ OUStringToOString(rpEvent->GetDescription(), RTL_TEXTENCODING_UTF8).getStr(),
+ rpEvent.get(),
+ rpEvent->getActivationTime(0.0));
+#endif
+
+ ENSURE_OR_RETURN_FALSE(
+ rpEvent.get() != NULL,
+ "EventQueue::addEvent: event ptr NULL");
+
+ maNextNextEvents.push(
+ EventEntry(
+ rpEvent,
+ rpEvent->getActivationTime(mpTimer->getElapsedTime())));
+
+ return true;
+ }
+
+ void EventQueue::forceEmpty()
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+ process_(true);
+ }
+
+ void EventQueue::process()
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+ process_(false);
+ }
+
+ void EventQueue::process_( bool bFireAllEvents )
+ {
+ VERBOSE_TRACE( "EventQueue: heartbeat" );
+
+ // add in all that have been added explicitly for this round:
+ EventEntryVector::const_iterator const iEnd( maNextEvents.end() );
+ for ( EventEntryVector::const_iterator iPos( maNextEvents.begin() );
+ iPos != iEnd; ++iPos ) {
+ maEvents.push(*iPos);
+ }
+ EventEntryVector().swap( maNextEvents );
+
+ // perform topmost, ready-to-execute event
+ // =======================================
+
+ const double nCurrTime( mpTimer->getElapsedTime() );
+
+ // When maEvents does not contain any events that are due now
+ // then process one event from maNextNextEvents.
+ if (!maNextNextEvents.empty()
+ && !bFireAllEvents
+ && (maEvents.empty() || maEvents.top().nTime > nCurrTime))
+ {
+ const EventEntry aEvent (maNextNextEvents.top());
+ maNextNextEvents.pop();
+ maEvents.push(aEvent);
+ }
+
+ // process ready/elapsed events. Note that the 'perceived'
+ // current time remains constant for this loop, thus we're
+ // processing only those events which where ready when we
+ // entered this method.
+ while( !maEvents.empty() &&
+ (bFireAllEvents || maEvents.top().nTime <= nCurrTime) )
+ {
+ EventEntry event( maEvents.top() );
+ maEvents.pop();
+
+ // only process event, if it is still 'charged',
+ // i.e. the fire() call effects something. This is
+ // used when e.g. having events registered at multiple
+ // places, which should fire only once: after the
+ // initial fire() call, those events become inactive
+ // and return false on isCharged. This frees us from
+ // the need to prune queues of those inactive shells.
+ if( event.pEvent->isCharged() )
+ {
+ try
+ {
+#if OSL_DEBUG_LEVEL > 0
+ VERBOSE_TRACE( "Firing event: unknown (0x%X), timeout was: %f",
+ event.pEvent.get(),
+ event.pEvent->getActivationTime(0.0) );
+#endif
+#if OSL_DEBUG_LEVEL > 1 && defined (SLIDESHOW_ADD_DESCRIPTIONS_TO_EVENTS)
+ OSL_TRACE("firing at %f event [%s] at %x with delay %f\r",
+ mpTimer->getElapsedTime(),
+ OUStringToOString(event.pEvent->GetDescription(),
+ RTL_TEXTENCODING_UTF8).getStr(),
+ event.pEvent.get(),
+ event.pEvent->getActivationTime(0.0));
+#endif
+
+ event.pEvent->fire();
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ // catch anything here, we don't want
+ // to leave this scope under _any_
+ // circumstance. Although, do _not_
+ // reinsert an activity that threw
+ // once.
+
+ // NOTE: we explicitely don't catch(...) here,
+ // since this will also capture segmentation
+ // violations and the like. In such a case, we
+ // still better let our clients now...
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ catch( SlideShowException& )
+ {
+ // catch anything here, we don't want
+ // to leave this scope under _any_
+ // circumstance. Although, do _not_
+ // reinsert an activity that threw
+ // once.
+
+ // NOTE: we explicitely don't catch(...) here,
+ // since this will also capture segmentation
+ // violations and the like. In such a case, we
+ // still better let our clients now...
+ OSL_TRACE( "::presentation::internal::EventQueue: Event threw a SlideShowException, action might not have been fully performed" );
+ }
+ }
+ else
+ {
+#if OSL_DEBUG_LEVEL > 0
+ VERBOSE_TRACE( "Ignoring discharged event: unknown (0x%X), timeout was: %f",
+ event.pEvent.get(),
+ event.pEvent->getActivationTime(0.0) );
+#endif
+ }
+ }
+ }
+
+ bool EventQueue::isEmpty() const
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+ return maEvents.empty() && maNextEvents.empty() && maNextNextEvents.empty();
+ }
+
+ double EventQueue::nextTimeout() const
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+ // return time for next entry (if any)
+ double nTimeout (::std::numeric_limits<double>::max());
+ const double nCurrentTime (mpTimer->getElapsedTime());
+ if ( ! maEvents.empty())
+ nTimeout = maEvents.top().nTime - nCurrentTime;
+ if ( ! maNextEvents.empty())
+ nTimeout = ::std::min(nTimeout, maNextEvents.front().nTime - nCurrentTime);
+ if ( ! maNextNextEvents.empty())
+ nTimeout = ::std::min(nTimeout, maNextNextEvents.top().nTime - nCurrentTime);
+
+ return nTimeout;
+ }
+
+ void EventQueue::clear()
+ {
+ ::osl::MutexGuard aGuard( maMutex );
+
+ // TODO(P1): Maybe a plain vector and vector.swap will
+ // be faster here. Profile.
+ maEvents = ImplQueueType();
+
+ maNextEvents.clear();
+ maNextNextEvents = ImplQueueType();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/expressionnodefactory.cxx b/slideshow/source/engine/expressionnodefactory.cxx
new file mode 100644
index 000000000000..14426cb59f21
--- /dev/null
+++ b/slideshow/source/engine/expressionnodefactory.cxx
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <expressionnodefactory.hxx>
+
+#include <canvas/verbosetrace.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+#include <functional>
+#include <algorithm>
+
+
+/* Implementation of ExpressionNodeFactory class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ namespace
+ {
+ class ConstantValueExpression : public ExpressionNode
+ {
+ public:
+ ConstantValueExpression( double rValue ) :
+ maValue( rValue )
+ {
+ }
+
+ virtual double operator()( double /*t*/ ) const
+ {
+ return maValue;
+ }
+
+ virtual bool isConstant() const
+ {
+ return true;
+ }
+
+ private:
+ double maValue;
+ };
+
+ class TValueExpression : public ExpressionNode
+ {
+ public:
+ TValueExpression()
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return t;
+ }
+
+ virtual bool isConstant() const
+ {
+ return false;
+ }
+ };
+
+ /** Base class for following binary functions (*+-/)
+
+ Does not pay off to have all this as a template, since
+ we'd have to hold the functor as a member (+33% object
+ size).
+ */
+ class BinaryExpressionBase : public ExpressionNode
+ {
+ public:
+ BinaryExpressionBase( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ mpFirstArg( rFirstArg ),
+ mpSecondArg( rSecondArg )
+ {
+ }
+
+ virtual bool isConstant() const
+ {
+ return
+ mpFirstArg->isConstant() &&
+ mpSecondArg->isConstant();
+ }
+
+ protected:
+ ExpressionNodeSharedPtr mpFirstArg;
+ ExpressionNodeSharedPtr mpSecondArg;
+ };
+
+ class PlusExpression : public BinaryExpressionBase
+ {
+ public:
+ PlusExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return (*mpFirstArg)(t) + (*mpSecondArg)(t);
+ }
+ };
+
+ class MinusExpression : public BinaryExpressionBase
+ {
+ public:
+ MinusExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return (*mpFirstArg)(t) - (*mpSecondArg)(t);
+ }
+ };
+
+ class MultipliesExpression : public BinaryExpressionBase
+ {
+ public:
+ MultipliesExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return (*mpFirstArg)(t) * (*mpSecondArg)(t);
+ }
+ };
+
+ class DividesExpression : public BinaryExpressionBase
+ {
+ public:
+ DividesExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return (*mpFirstArg)(t) / (*mpSecondArg)(t);
+ }
+ };
+
+ class ComposedExpression : public BinaryExpressionBase
+ {
+ public:
+ ComposedExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return (*mpFirstArg)( (*mpSecondArg)(t) );
+ }
+ };
+
+ class MinExpression : public BinaryExpressionBase
+ {
+ public:
+ MinExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return ::std::min( (*mpFirstArg)(t), (*mpSecondArg)(t) );
+ }
+ };
+
+ class MaxExpression : public BinaryExpressionBase
+ {
+ public:
+ MaxExpression( const ExpressionNodeSharedPtr& rFirstArg,
+ const ExpressionNodeSharedPtr& rSecondArg ) :
+ BinaryExpressionBase( rFirstArg, rSecondArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return ::std::max( (*mpFirstArg)(t), (*mpSecondArg)(t) );
+ }
+ };
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createConstantValueExpression( double rConstantValue )
+ {
+ return ExpressionNodeSharedPtr( new ConstantValueExpression(rConstantValue) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createValueTExpression()
+ {
+ return ExpressionNodeSharedPtr( new TValueExpression() );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createPlusExpression( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS )
+ {
+ return ExpressionNodeSharedPtr( new PlusExpression(rLHS, rRHS) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createMinusExpression( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS )
+ {
+ return ExpressionNodeSharedPtr( new MinusExpression(rLHS, rRHS) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createMultipliesExpression( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS )
+ {
+ return ExpressionNodeSharedPtr( new MultipliesExpression(rLHS, rRHS) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createDividesExpression( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS )
+ {
+ return ExpressionNodeSharedPtr( new DividesExpression(rLHS, rRHS) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createComposedExpression ( const ExpressionNodeSharedPtr& rOuterFunction,
+ const ExpressionNodeSharedPtr& rInnerFunction )
+ {
+ return ExpressionNodeSharedPtr( new ComposedExpression(rOuterFunction, rInnerFunction) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createMinExpression ( const ExpressionNodeSharedPtr& rOuterFunction,
+ const ExpressionNodeSharedPtr& rInnerFunction )
+ {
+ return ExpressionNodeSharedPtr( new MinExpression(rOuterFunction, rInnerFunction) );
+ }
+
+ ExpressionNodeSharedPtr ExpressionNodeFactory::createMaxExpression ( const ExpressionNodeSharedPtr& rOuterFunction,
+ const ExpressionNodeSharedPtr& rInnerFunction )
+ {
+ return ExpressionNodeSharedPtr( new MaxExpression(rOuterFunction, rInnerFunction) );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/makefile.mk b/slideshow/source/engine/makefile.mk
new file mode 100644
index 000000000000..beac66778518
--- /dev/null
+++ b/slideshow/source/engine/makefile.mk
@@ -0,0 +1,102 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=slideshow
+TARGET=engine
+ENABLE_EXCEPTIONS=TRUE
+
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+.IF "$(ENABLE_PRESENTER_EXTRA_UI)"=="YES"
+CDEFS+=-DENABLE_PRESENTER_EXTRA_UI
+.ENDIF
+
+# --- Common ----------------------------------------------------------
+
+ENVCFLAGS += -DBOOST_SPIRIT_USE_OLD_NAMESPACE
+
+.IF "$(OS)"=="SOLARIS"
+.IF "$(CCNUMVER)"=="00050009"
+# SunStudio12: anachronism warning in boost code (smilfunctionparser.cxx)
+# reevaluate with newer boost or compiler version
+CFLAGSWARNCXX!:=$(CFLAGSWARNCXX),badargtype2w
+.ENDIF
+.ENDIF
+
+# Disable optimization for SunCC Sparc (funny loops
+# when parsing e.g. "x+width/2")
+# Do not disable optimization for SunCC++ 5.5 Solaris x86,
+# this compiler has an ICE on smilfunctionparser.cxx *without*
+# optimization
+.IF "$(OS)$(CPU)"=="SOLARISS" && "$(COM)"!="GCC"
+NOOPTFILES= $(SLO)$/smilfunctionparser.obj
+.ENDIF
+# same issue for MACOSX
+.IF "$(OS)"=="MACOSX"
+NOOPTFILES= $(SLO)$/smilfunctionparser.obj
+.ENDIF
+
+SLOFILES = $(SLO)$/activitiesqueue.obj \
+ $(SLO)$/animatedsprite.obj \
+ $(SLO)$/animationfactory.obj \
+ $(SLO)$/attributemap.obj \
+ $(SLO)$/color.obj \
+ $(SLO)$/delayevent.obj \
+ $(SLO)$/effectrewinder.obj \
+ $(SLO)$/eventmultiplexer.obj \
+ $(SLO)$/eventqueue.obj \
+ $(SLO)$/expressionnodefactory.obj \
+ $(SLO)$/rehearsetimingsactivity.obj \
+ $(SLO)$/screenupdater.obj \
+ $(SLO)$/shapeattributelayer.obj \
+ $(SLO)$/shapesubset.obj \
+ $(SLO)$/slidebitmap.obj \
+ $(SLO)$/slideshowcontext.obj \
+ $(SLO)$/slideshowimpl.obj \
+ $(SLO)$/slideview.obj \
+ $(SLO)$/smilfunctionparser.obj \
+ $(SLO)$/soundplayer.obj \
+ $(SLO)$/tools.obj \
+ $(SLO)$/unoviewcontainer.obj \
+ $(SLO)$/usereventqueue.obj \
+ $(SLO)$/waitsymbol.obj \
+ $(SLO)$/wakeupevent.obj \
+ $(SLO)$/debug.obj
+
+.IF "$(debug)"!="" || "$(DEBUG)"!=""
+SLOFILES += $(SLO)$/sp_debug.obj
+.ENDIF
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/rehearsetimingsactivity.cxx b/slideshow/source/engine/rehearsetimingsactivity.cxx
new file mode 100644
index 000000000000..6ba5aae1e5de
--- /dev/null
+++ b/slideshow/source/engine/rehearsetimingsactivity.cxx
@@ -0,0 +1,584 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <boost/current_function.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/metric.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/awt/MouseEvent.hpp>
+#include <com/sun/star/rendering/XBitmap.hpp>
+
+#include "eventqueue.hxx"
+#include "screenupdater.hxx"
+#include "eventmultiplexer.hxx"
+#include "activitiesqueue.hxx"
+#include "slideshowcontext.hxx"
+#include "mouseeventhandler.hxx"
+#include "rehearsetimingsactivity.hxx"
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+namespace slideshow {
+namespace internal {
+
+class RehearseTimingsActivity::WakeupEvent : public Event,
+ private ::boost::noncopyable
+{
+public:
+ WakeupEvent( boost::shared_ptr< ::canvas::tools::ElapsedTime > const& pTimeBase,
+ ActivitySharedPtr const& rActivity,
+ ActivitiesQueue & rActivityQueue ) :
+#if OSL_DEBUG_LEVEL > 1
+ Event(::rtl::OUString::createFromAscii("WakeupEvent")),
+#endif
+ maTimer(pTimeBase),
+ mnNextTime(0.0),
+ mpActivity(rActivity),
+ mrActivityQueue( rActivityQueue )
+ {}
+
+ virtual void dispose() {}
+ virtual bool fire()
+ {
+ ActivitySharedPtr pActivity( mpActivity.lock() );
+ if( !pActivity )
+ return false;
+
+ return mrActivityQueue.addActivity( pActivity );
+ }
+
+ virtual bool isCharged() const { return true; }
+ virtual double getActivationTime( double nCurrentTime ) const
+ {
+ const double nElapsedTime( maTimer.getElapsedTime() );
+
+ return ::std::max( nCurrentTime,
+ nCurrentTime - nElapsedTime + mnNextTime );
+ }
+
+ /// Start the internal timer
+ void start() { maTimer.reset(); }
+
+ /** Set the next timeout this object should generate.
+
+ @param nextTime
+ Absolute time, measured from the last start() call,
+ when this event should wakeup the Activity again. If
+ your time is relative, simply call start() just before
+ every setNextTimeout() call.
+ */
+ void setNextTimeout( double nextTime ) { mnNextTime = nextTime; }
+
+private:
+ ::canvas::tools::ElapsedTime maTimer;
+ double mnNextTime;
+ boost::weak_ptr<Activity> mpActivity;
+ ActivitiesQueue& mrActivityQueue;
+};
+
+class RehearseTimingsActivity::MouseHandler : public MouseEventHandler,
+ private boost::noncopyable
+{
+public:
+ explicit MouseHandler( RehearseTimingsActivity& rta );
+
+ void reset();
+ bool hasBeenClicked() const { return mbHasBeenClicked; }
+
+ // MouseEventHandler
+ virtual bool handleMousePressed( awt::MouseEvent const & evt );
+ virtual bool handleMouseReleased( awt::MouseEvent const & evt );
+ virtual bool handleMouseEntered( awt::MouseEvent const & evt );
+ virtual bool handleMouseExited( awt::MouseEvent const & evt );
+ virtual bool handleMouseDragged( awt::MouseEvent const & evt );
+ virtual bool handleMouseMoved( awt::MouseEvent const & evt );
+
+private:
+ bool isInArea( com::sun::star::awt::MouseEvent const & evt ) const;
+ void updatePressedState( const bool pressedState ) const;
+
+ RehearseTimingsActivity& mrActivity;
+ bool mbHasBeenClicked;
+ bool mbMouseStartedInArea;
+};
+
+const sal_Int32 LEFT_BORDER_SPACE = 10;
+const sal_Int32 LOWER_BORDER_SPACE = 30;
+
+RehearseTimingsActivity::RehearseTimingsActivity( const SlideShowContext& rContext ) :
+ mrEventQueue(rContext.mrEventQueue),
+ mrScreenUpdater(rContext.mrScreenUpdater),
+ mrEventMultiplexer(rContext.mrEventMultiplexer),
+ mrActivitiesQueue(rContext.mrActivitiesQueue),
+ maElapsedTime( rContext.mrEventQueue.getTimer() ),
+ maViews(),
+ maSpriteRectangle(),
+ maFont( Application::GetSettings().GetStyleSettings().GetInfoFont() ),
+ mpWakeUpEvent(),
+ mpMouseHandler(),
+ maSpriteSizePixel(),
+ mnYOffset(0),
+ mbActive(false),
+ mbDrawPressed(false)
+{
+ maFont.SetHeight( maFont.GetHeight() * 2 );
+ maFont.SetWidth( maFont.GetWidth() * 2 );
+ maFont.SetAlign( ALIGN_BASELINE );
+ maFont.SetColor( COL_BLACK );
+
+ // determine sprite size (in pixel):
+ VirtualDevice blackHole;
+ blackHole.EnableOutput(false);
+ blackHole.SetFont( maFont );
+ blackHole.SetMapMode( MAP_PIXEL );
+ Rectangle rect;
+ const FontMetric metric( blackHole.GetFontMetric() );
+ blackHole.GetTextBoundRect(
+ rect, String(RTL_CONSTASCII_USTRINGPARAM("XX:XX:XX")) );
+ maSpriteSizePixel.setX( rect.getWidth() * 12 / 10 );
+ maSpriteSizePixel.setY( metric.GetLineHeight() * 11 / 10 );
+ mnYOffset = (metric.GetAscent() + (metric.GetLineHeight() / 20));
+
+ std::for_each( rContext.mrViewContainer.begin(),
+ rContext.mrViewContainer.end(),
+ boost::bind( &RehearseTimingsActivity::viewAdded,
+ this,
+ _1 ));
+}
+
+RehearseTimingsActivity::~RehearseTimingsActivity()
+{
+ try
+ {
+ stop();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+}
+
+boost::shared_ptr<RehearseTimingsActivity> RehearseTimingsActivity::create(
+ const SlideShowContext& rContext )
+{
+ boost::shared_ptr<RehearseTimingsActivity> pActivity(
+ new RehearseTimingsActivity( rContext ));
+
+ pActivity->mpMouseHandler.reset(
+ new MouseHandler(*pActivity.get()) );
+ pActivity->mpWakeUpEvent.reset(
+ new WakeupEvent( rContext.mrEventQueue.getTimer(),
+ pActivity,
+ rContext.mrActivitiesQueue ));
+
+ rContext.mrEventMultiplexer.addViewHandler( pActivity );
+
+ return pActivity;
+}
+
+void RehearseTimingsActivity::start()
+{
+ maElapsedTime.reset();
+ mbDrawPressed = false;
+ mbActive = true;
+
+ // paint and show all sprites:
+ paintAllSprites();
+ for_each_sprite( boost::bind( &cppcanvas::Sprite::show, _1 ) );
+
+ mrActivitiesQueue.addActivity( shared_from_this() );
+
+ mpMouseHandler->reset();
+ mrEventMultiplexer.addClickHandler(
+ mpMouseHandler, 42 /* highest prio of all, > 3.0 */ );
+ mrEventMultiplexer.addMouseMoveHandler(
+ mpMouseHandler, 42 /* highest prio of all, > 3.0 */ );
+}
+
+double RehearseTimingsActivity::stop()
+{
+ mrEventMultiplexer.removeMouseMoveHandler( mpMouseHandler );
+ mrEventMultiplexer.removeClickHandler( mpMouseHandler );
+
+ mbActive = false; // will be removed from queue
+
+ for_each_sprite( boost::bind( &cppcanvas::Sprite::hide, _1 ) );
+
+ return maElapsedTime.getElapsedTime();
+}
+
+bool RehearseTimingsActivity::hasBeenClicked() const
+{
+ if (mpMouseHandler)
+ return mpMouseHandler->hasBeenClicked();
+ return false;
+}
+
+// Disposable:
+void RehearseTimingsActivity::dispose()
+{
+ stop();
+
+ mpWakeUpEvent.reset();
+ mpMouseHandler.reset();
+
+ ViewsVecT().swap( maViews );
+}
+
+// Activity:
+double RehearseTimingsActivity::calcTimeLag() const
+{
+ return 0.0;
+}
+
+bool RehearseTimingsActivity::perform()
+{
+ if( !isActive() )
+ return false;
+
+ if( !mpWakeUpEvent )
+ return false;
+
+ mpWakeUpEvent->start();
+ mpWakeUpEvent->setNextTimeout( 0.5 );
+ mrEventQueue.addEvent( mpWakeUpEvent );
+
+ paintAllSprites();
+
+ // sprites changed, need screen update
+ mrScreenUpdater.notifyUpdate();
+
+ return false; // don't reinsert, WakeupEvent will perform
+ // that after the given timeout
+}
+
+bool RehearseTimingsActivity::isActive() const
+{
+ return mbActive;
+}
+
+void RehearseTimingsActivity::dequeued()
+{
+ // not used here
+}
+
+void RehearseTimingsActivity::end()
+{
+ if (isActive())
+ {
+ stop();
+ mbActive = false;
+ }
+}
+
+basegfx::B2DRange RehearseTimingsActivity::calcSpriteRectangle( UnoViewSharedPtr const& rView ) const
+{
+ const Reference<rendering::XBitmap> xBitmap( rView->getCanvas()->getUNOCanvas(),
+ UNO_QUERY );
+ if( !xBitmap.is() )
+ return basegfx::B2DRange();
+
+ const geometry::IntegerSize2D realSize( xBitmap->getSize() );
+ // pixel:
+ basegfx::B2DPoint spritePos(
+ std::min<sal_Int32>( realSize.Width, LEFT_BORDER_SPACE ),
+ std::max<sal_Int32>( 0, realSize.Height - maSpriteSizePixel.getY()
+ - LOWER_BORDER_SPACE ) );
+ basegfx::B2DHomMatrix transformation( rView->getTransformation() );
+ transformation.invert();
+ spritePos *= transformation;
+ basegfx::B2DSize spriteSize( maSpriteSizePixel.getX(),
+ maSpriteSizePixel.getY() );
+ spriteSize *= transformation;
+ return basegfx::B2DRange(
+ spritePos.getX(), spritePos.getY(),
+ spritePos.getX() + spriteSize.getX(),
+ spritePos.getY() + spriteSize.getY() );
+}
+
+void RehearseTimingsActivity::viewAdded( const UnoViewSharedPtr& rView )
+{
+ cppcanvas::CustomSpriteSharedPtr sprite(
+ rView->createSprite( basegfx::B2DSize(
+ maSpriteSizePixel.getX()+2,
+ maSpriteSizePixel.getY()+2 ),
+ 1001.0 )); // sprite should be in front of all
+ // other sprites
+ sprite->setAlpha( 0.8 );
+ const basegfx::B2DRange spriteRectangle(
+ calcSpriteRectangle( rView ) );
+ sprite->move( basegfx::B2DPoint(
+ spriteRectangle.getMinX(),
+ spriteRectangle.getMinY() ) );
+
+ if( maViews.empty() )
+ maSpriteRectangle = spriteRectangle;
+
+ maViews.push_back( ViewsVecT::value_type( rView, sprite ) );
+
+ if (isActive())
+ sprite->show();
+}
+
+void RehearseTimingsActivity::viewRemoved( const UnoViewSharedPtr& rView )
+{
+ maViews.erase(
+ std::remove_if(
+ maViews.begin(), maViews.end(),
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind( std::select1st<ViewsVecT::value_type>(), _1 ))),
+ maViews.end() );
+}
+
+void RehearseTimingsActivity::viewChanged( const UnoViewSharedPtr& rView )
+{
+ // find entry corresponding to modified view
+ ViewsVecT::iterator aModifiedEntry(
+ std::find_if(
+ maViews.begin(),
+ maViews.end(),
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind( std::select1st<ViewsVecT::value_type>(), _1 ))));
+
+ OSL_ASSERT( aModifiedEntry != maViews.end() );
+ if( aModifiedEntry == maViews.end() )
+ return;
+
+ // new sprite pos, transformation might have changed:
+ maSpriteRectangle = calcSpriteRectangle( rView );
+
+ // reposition sprite:
+ aModifiedEntry->second->move( maSpriteRectangle.getMinimum() );
+
+ // sprites changed, need screen update
+ mrScreenUpdater.notifyUpdate( rView );
+}
+
+void RehearseTimingsActivity::viewsChanged()
+{
+ if( !maViews.empty() )
+ {
+ // new sprite pos, transformation might have changed:
+ maSpriteRectangle = calcSpriteRectangle( maViews.front().first );
+
+ // reposition sprites
+ for_each_sprite( boost::bind( &cppcanvas::Sprite::move,
+ _1,
+ boost::cref(maSpriteRectangle.getMinimum())) );
+
+ // sprites changed, need screen update
+ mrScreenUpdater.notifyUpdate();
+ }
+}
+
+void RehearseTimingsActivity::paintAllSprites() const
+{
+ for_each_sprite(
+ boost::bind( &RehearseTimingsActivity::paint, this,
+ // call getContentCanvas() on each sprite:
+ boost::bind(
+ &cppcanvas::CustomSprite::getContentCanvas, _1 ) ) );
+}
+
+void RehearseTimingsActivity::paint( cppcanvas::CanvasSharedPtr const & canvas ) const
+{
+ // build timer string:
+ const sal_Int32 nTimeSecs =
+ static_cast<sal_Int32>(maElapsedTime.getElapsedTime());
+ rtl::OUStringBuffer buf;
+ sal_Int32 n = (nTimeSecs / 3600);
+ if (n < 10)
+ buf.append( static_cast<sal_Unicode>('0') );
+ buf.append( n );
+ buf.append( static_cast<sal_Unicode>(':') );
+ n = ((nTimeSecs % 3600) / 60);
+ if (n < 10)
+ buf.append( static_cast<sal_Unicode>('0') );
+ buf.append( n );
+ buf.append( static_cast<sal_Unicode>(':') );
+ n = (nTimeSecs % 60);
+ if (n < 10)
+ buf.append( static_cast<sal_Unicode>('0') );
+ buf.append( n );
+ const rtl::OUString time = buf.makeStringAndClear();
+
+ // create the MetaFile:
+ GDIMetaFile metaFile;
+ VirtualDevice blackHole;
+ metaFile.Record( &blackHole );
+ metaFile.SetPrefSize( Size( 1, 1 ) );
+ blackHole.EnableOutput(false);
+ blackHole.SetMapMode( MAP_PIXEL );
+ blackHole.SetFont( maFont );
+ Rectangle rect = Rectangle( 0,0,
+ maSpriteSizePixel.getX(),
+ maSpriteSizePixel.getY());
+ if (mbDrawPressed)
+ {
+ blackHole.SetTextColor( COL_BLACK );
+ blackHole.SetFillColor( COL_LIGHTGRAY );
+ blackHole.SetLineColor( COL_GRAY );
+ }
+ else
+ {
+ blackHole.SetTextColor( COL_BLACK );
+ blackHole.SetFillColor( COL_WHITE );
+ blackHole.SetLineColor( COL_GRAY );
+ }
+ blackHole.DrawRect( rect );
+ blackHole.GetTextBoundRect( rect, time );
+ blackHole.DrawText(
+ Point( (maSpriteSizePixel.getX() - rect.getWidth()) / 2,
+ mnYOffset ), time );
+
+ metaFile.Stop();
+ metaFile.WindStart();
+
+ cppcanvas::RendererSharedPtr renderer(
+ cppcanvas::VCLFactory::getInstance().createRenderer(
+ canvas, metaFile, cppcanvas::Renderer::Parameters() ) );
+ const bool succ = renderer->draw();
+ OSL_ASSERT( succ );
+ (void)succ;
+}
+
+
+RehearseTimingsActivity::MouseHandler::MouseHandler( RehearseTimingsActivity& rta ) :
+ mrActivity(rta),
+ mbHasBeenClicked(false),
+ mbMouseStartedInArea(false)
+{}
+
+void RehearseTimingsActivity::MouseHandler::reset()
+{
+ mbHasBeenClicked = false;
+ mbMouseStartedInArea = false;
+}
+
+bool RehearseTimingsActivity::MouseHandler::isInArea(
+ awt::MouseEvent const & evt ) const
+{
+ return mrActivity.maSpriteRectangle.isInside(
+ basegfx::B2DPoint( evt.X, evt.Y ) );
+}
+
+void RehearseTimingsActivity::MouseHandler::updatePressedState(
+ const bool pressedState ) const
+{
+ if( pressedState != mrActivity.mbDrawPressed )
+ {
+ mrActivity.mbDrawPressed = pressedState;
+ mrActivity.paintAllSprites();
+
+ mrActivity.mrScreenUpdater.notifyUpdate();
+ }
+}
+
+// MouseEventHandler
+bool RehearseTimingsActivity::MouseHandler::handleMousePressed(
+ awt::MouseEvent const & evt )
+{
+ if( evt.Buttons == awt::MouseButton::LEFT && isInArea(evt) )
+ {
+ mbMouseStartedInArea = true;
+ updatePressedState(true);
+ return true; // consume event
+ }
+ return false;
+}
+
+bool RehearseTimingsActivity::MouseHandler::handleMouseReleased(
+ awt::MouseEvent const & evt )
+{
+ if( evt.Buttons == awt::MouseButton::LEFT && mbMouseStartedInArea )
+ {
+ mbHasBeenClicked = isInArea(evt); // fini if in
+ mbMouseStartedInArea = false;
+ updatePressedState(false);
+ if( !mbHasBeenClicked )
+ return true; // consume event, else next slide (manual advance)
+ }
+ return false;
+}
+
+bool RehearseTimingsActivity::MouseHandler::handleMouseEntered(
+ awt::MouseEvent const & /*evt*/ )
+{
+ return false;
+}
+
+bool RehearseTimingsActivity::MouseHandler::handleMouseExited(
+ awt::MouseEvent const & /*evt*/ )
+{
+ return false;
+}
+
+bool RehearseTimingsActivity::MouseHandler::handleMouseDragged(
+ awt::MouseEvent const & evt )
+{
+ if( mbMouseStartedInArea )
+ updatePressedState( isInArea(evt) );
+ return false;
+}
+
+bool RehearseTimingsActivity::MouseHandler::handleMouseMoved(
+ awt::MouseEvent const & /*evt*/ )
+{
+ return false;
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/rehearsetimingsactivity.hxx b/slideshow/source/engine/rehearsetimingsactivity.hxx
new file mode 100644
index 000000000000..2132875911d6
--- /dev/null
+++ b/slideshow/source/engine/rehearsetimingsactivity.hxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_REHEARSETIMINGSACTIVITY_HXX
+#define INCLUDED_SLIDESHOW_REHEARSETIMINGSACTIVITY_HXX
+
+#include "activity.hxx"
+
+#include <basegfx/range/b2drange.hxx>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <vector>
+#include <utility>
+
+class Font;
+namespace canvas{ namespace tools{ class ElapsedTime; }}
+namespace cppcanvas{ class CustomSprite; }
+namespace basegfx
+{
+ class B2IVector;
+ class B2DRange;
+}
+
+namespace slideshow {
+namespace internal {
+
+struct SlideShowContext;
+class EventMultiplexer;
+class ScreenUpdater;
+class RehearseTimingsActivity : public Activity,
+ public ViewEventHandler,
+ public boost::enable_shared_from_this<RehearseTimingsActivity>,
+ private ::boost::noncopyable
+{
+public:
+ /** Creates the activity.
+ */
+ static boost::shared_ptr<RehearseTimingsActivity> create(
+ const SlideShowContext& rContext );
+
+ virtual ~RehearseTimingsActivity();
+
+ /** Starts and shows the timer; adds to activity queue.
+ */
+ void start();
+
+ /** Stops and hides the timer.
+ @return elapsed time
+ */
+ double stop();
+
+ /** Determines whether the timer button has been clicked.
+ */
+ bool hasBeenClicked() const;
+
+ // ViewEventHandler interface
+ virtual void viewAdded( const UnoViewSharedPtr& rView );
+ virtual void viewRemoved( const UnoViewSharedPtr& rView );
+ virtual void viewChanged( const UnoViewSharedPtr& rView );
+ virtual void viewsChanged();
+
+ // Disposable:
+ virtual void dispose();
+ // Activity:
+ virtual double calcTimeLag() const;
+ virtual bool perform();
+ virtual bool isActive() const;
+ virtual void dequeued();
+ virtual void end();
+
+private:
+ class WakeupEvent;
+
+ explicit RehearseTimingsActivity( const SlideShowContext& rContext );
+
+ void paint( ::cppcanvas::CanvasSharedPtr const & canvas ) const;
+ void paintAllSprites() const;
+
+ class MouseHandler;
+ friend class MouseHandler;
+
+ typedef ::std::vector<
+ ::std::pair<UnoViewSharedPtr,
+ boost::shared_ptr<cppcanvas::CustomSprite> > > ViewsVecT;
+
+ template <typename func_type>
+ void for_each_sprite( func_type const & func ) const
+ {
+ ViewsVecT::const_iterator iPos( maViews.begin() );
+ const ViewsVecT::const_iterator iEnd( maViews.end() );
+ for ( ; iPos != iEnd; ++iPos )
+ func( iPos->second );
+ }
+
+ ::basegfx::B2DRange calcSpriteRectangle(
+ UnoViewSharedPtr const & rView ) const;
+
+ EventQueue& mrEventQueue;
+ ScreenUpdater& mrScreenUpdater;
+ EventMultiplexer& mrEventMultiplexer;
+ ActivitiesQueue& mrActivitiesQueue;
+ canvas::tools::ElapsedTime maElapsedTime;
+
+ ViewsVecT maViews;
+
+ /// screen rect of sprite (in view coordinates!)
+ ::basegfx::B2DRange maSpriteRectangle;
+
+ Font maFont;
+ boost::shared_ptr<WakeupEvent> mpWakeUpEvent;
+ boost::shared_ptr<MouseHandler> mpMouseHandler;
+ ::basegfx::B2IVector maSpriteSizePixel;
+ sal_Int32 mnYOffset;
+ bool mbActive;
+ bool mbDrawPressed;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_REHEARSETIMINGSACTIVITY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/screenupdater.cxx b/slideshow/source/engine/screenupdater.cxx
new file mode 100644
index 000000000000..5d39b23c0901
--- /dev/null
+++ b/slideshow/source/engine/screenupdater.cxx
@@ -0,0 +1,271 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_slideshow.hxx"
+
+#include "screenupdater.hxx"
+#include "listenercontainer.hxx"
+
+#include <boost/bind.hpp>
+#include <vector>
+#include <algorithm>
+
+namespace {
+ class UpdateLock : public ::slideshow::internal::ScreenUpdater::UpdateLock
+ {
+ public:
+ UpdateLock (::slideshow::internal::ScreenUpdater& rUpdater, const bool bStartLocked);
+ virtual ~UpdateLock (void);
+ virtual void Activate (void);
+ private:
+ ::slideshow::internal::ScreenUpdater& mrUpdater;
+ bool mbIsActivated;
+ };
+}
+
+namespace slideshow
+{
+namespace internal
+{
+ typedef std::vector<
+ std::pair<UnoViewSharedPtr,bool> > UpdateRequestVector;
+
+ struct ScreenUpdater::ImplScreenUpdater
+ {
+ /** List of registered ViewUpdaters, to consult for necessary
+ updates
+ */
+ ThreadUnsafeListenerContainer<
+ ViewUpdateSharedPtr,
+ std::vector<ViewUpdateSharedPtr> > maUpdaters;
+
+ /// Views that have been notified for update
+ UpdateRequestVector maViewUpdateRequests;
+
+ /// List of View. Used to issue screen updates on.
+ UnoViewContainer const& mrViewContainer;
+
+ /// True, if a notifyUpdate() for all views has been issued.
+ bool mbUpdateAllRequest;
+
+ /// True, if at least one notifyUpdate() call had bViewClobbered set
+ bool mbViewClobbered;
+
+ /// The screen is updated only when mnLockCount==0
+ sal_Int32 mnLockCount;
+
+ explicit ImplScreenUpdater( UnoViewContainer const& rViewContainer ) :
+ maUpdaters(),
+ maViewUpdateRequests(),
+ mrViewContainer(rViewContainer),
+ mbUpdateAllRequest(false),
+ mbViewClobbered(false),
+ mnLockCount(0)
+ {}
+ };
+
+ ScreenUpdater::ScreenUpdater( UnoViewContainer const& rViewContainer ) :
+ mpImpl(new ImplScreenUpdater(rViewContainer) )
+ {
+ }
+
+ ScreenUpdater::~ScreenUpdater()
+ {
+ // outline because of pimpl
+ }
+
+ void ScreenUpdater::notifyUpdate()
+ {
+ mpImpl->mbUpdateAllRequest = true;
+ }
+
+ void ScreenUpdater::notifyUpdate( const UnoViewSharedPtr& rView,
+ bool bViewClobbered )
+ {
+ mpImpl->maViewUpdateRequests.push_back(
+ std::make_pair(rView, bViewClobbered) );
+
+ if( bViewClobbered )
+ mpImpl->mbViewClobbered = true;
+ }
+
+ void ScreenUpdater::commitUpdates()
+ {
+ if (mpImpl->mnLockCount > 0)
+ return;
+
+ // cases:
+ //
+ // (a) no update necessary at all
+ //
+ // (b) no ViewUpdate-generated update
+ // I. update all views requested -> for_each( mrViewContainer )
+ // II. update some views requested -> for_each( maViewUpdateRequests )
+ //
+ // (c) ViewUpdate-triggered update - update all views
+ //
+
+ // any ViewUpdate-triggered updates?
+ const bool bViewUpdatesNeeded(
+ mpImpl->maUpdaters.apply(
+ boost::mem_fn(&ViewUpdate::needsUpdate)) );
+
+ if( bViewUpdatesNeeded )
+ {
+ mpImpl->maUpdaters.applyAll(
+ boost::mem_fn((bool (ViewUpdate::*)())&ViewUpdate::update) );
+ }
+
+ if( bViewUpdatesNeeded ||
+ mpImpl->mbUpdateAllRequest )
+ {
+ // unconditionally update all views
+ std::for_each( mpImpl->mrViewContainer.begin(),
+ mpImpl->mrViewContainer.end(),
+ mpImpl->mbViewClobbered ?
+ boost::mem_fn(&View::paintScreen) :
+ boost::mem_fn(&View::updateScreen) );
+ }
+ else if( !mpImpl->maViewUpdateRequests.empty() )
+ {
+ // update notified views only
+ UpdateRequestVector::const_iterator aIter(
+ mpImpl->maViewUpdateRequests.begin() );
+ const UpdateRequestVector::const_iterator aEnd(
+ mpImpl->maViewUpdateRequests.end() );
+ while( aIter != aEnd )
+ {
+ // TODO(P1): this is O(n^2) in the number of views, if
+ // lots of views notify updates.
+ const UnoViewVector::const_iterator aEndOfViews(
+ mpImpl->mrViewContainer.end() );
+ UnoViewVector::const_iterator aFoundView;
+ if( (aFoundView=std::find(mpImpl->mrViewContainer.begin(),
+ aEndOfViews,
+ aIter->first)) != aEndOfViews )
+ {
+ if( aIter->second )
+ (*aFoundView)->paintScreen(); // force-paint
+ else
+ (*aFoundView)->updateScreen(); // update changes only
+ }
+
+ ++aIter;
+ }
+ }
+
+ // done - clear requests
+ mpImpl->mbViewClobbered = false;
+ mpImpl->mbUpdateAllRequest = false;
+ UpdateRequestVector().swap( mpImpl->maViewUpdateRequests );
+ }
+
+ void ScreenUpdater::addViewUpdate( ViewUpdateSharedPtr const& rViewUpdate )
+ {
+ mpImpl->maUpdaters.add( rViewUpdate );
+ }
+
+ void ScreenUpdater::removeViewUpdate( ViewUpdateSharedPtr const& rViewUpdate )
+ {
+ mpImpl->maUpdaters.remove( rViewUpdate );
+ }
+
+ void ScreenUpdater::requestImmediateUpdate()
+ {
+ if (mpImpl->mnLockCount > 0)
+ return;
+
+ // TODO(F2): This will interfere with other updates, since it
+ // happens out-of-sync with main animation loop. Might cause
+ // artifacts.
+ std::for_each( mpImpl->mrViewContainer.begin(),
+ mpImpl->mrViewContainer.end(),
+ boost::mem_fn(&View::updateScreen) );
+ }
+
+ void ScreenUpdater::lockUpdates (void)
+ {
+ ++mpImpl->mnLockCount;
+ OSL_ASSERT(mpImpl->mnLockCount>0);
+ }
+
+ void ScreenUpdater::unlockUpdates (void)
+ {
+ OSL_ASSERT(mpImpl->mnLockCount>0);
+ if (mpImpl->mnLockCount > 0)
+ {
+ --mpImpl->mnLockCount;
+ if (mpImpl->mnLockCount)
+ commitUpdates();
+ }
+ }
+
+ ::boost::shared_ptr<ScreenUpdater::UpdateLock> ScreenUpdater::createLock (const bool bStartLocked)
+ {
+ return ::boost::shared_ptr<ScreenUpdater::UpdateLock>(new ::UpdateLock(*this, bStartLocked));
+ }
+
+
+} // namespace internal
+} // namespace slideshow
+
+namespace {
+
+UpdateLock::UpdateLock (
+ ::slideshow::internal::ScreenUpdater& rUpdater,
+ const bool bStartLocked)
+ : mrUpdater(rUpdater),
+ mbIsActivated(false)
+{
+ if (bStartLocked)
+ Activate();
+}
+
+
+
+
+UpdateLock::~UpdateLock (void)
+{
+ if (mbIsActivated)
+ mrUpdater.unlockUpdates();
+}
+
+
+
+
+void UpdateLock::Activate (void)
+{
+ if ( ! mbIsActivated)
+ {
+ mbIsActivated = true;
+ mrUpdater.lockUpdates();
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapeattributelayer.cxx b/slideshow/source/engine/shapeattributelayer.cxx
new file mode 100644
index 000000000000..c17da20a408e
--- /dev/null
+++ b/slideshow/source/engine/shapeattributelayer.cxx
@@ -0,0 +1,859 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <shapeattributelayer.hxx>
+
+#include <canvas/verbosetrace.hxx>
+
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <rtl/math.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Update state ids
+
+ This method updates all state IDs from possible
+ children. Whenever a child's state ID changed, we
+ increment ours.
+ */
+ void ShapeAttributeLayer::updateStateIds()
+ {
+ if( haveChild() )
+ {
+ if( mnTransformationState != mpChild->getTransformationState() )
+ ++mnTransformationState;
+ if( mnClipState != mpChild->getClipState() )
+ ++mnClipState;
+ if( mnAlphaState != mpChild->getAlphaState() )
+ ++mnAlphaState;
+ if( mnPositionState != mpChild->getPositionState() )
+ ++mnPositionState;
+ if( mnContentState != mpChild->getContentState() )
+ ++mnContentState;
+ if( mnVisibilityState != mpChild->getVisibilityState() )
+ ++mnVisibilityState;
+ }
+ }
+
+ /** Calc attribute value.
+
+ This method determines the current attribute value,
+ appropriately combining it with children values (by
+ evaluating the mnAdditiveMode member).
+ */
+ template< typename T > T ShapeAttributeLayer::calcValue( const T& rCurrValue,
+ bool bThisInstanceValid,
+ bool (ShapeAttributeLayer::*pIsValid)() const,
+ T (ShapeAttributeLayer::*pGetValue)() const ) const
+ {
+ // deviated from the (*shared_ptr).*mpFuncPtr notation
+ // here, since gcc does not seem to parse that as a member
+ // function call anymore.
+ const bool bChildInstanceValueValid( haveChild() ? (mpChild.get()->*pIsValid)() : false );
+
+ if( bThisInstanceValid )
+ {
+ if( bChildInstanceValueValid )
+ {
+ // merge with child value
+ switch( mnAdditiveMode )
+ {
+ default:
+ // FALTHROUGH intended
+ case animations::AnimationAdditiveMode::NONE:
+ // FALTHROUGH intended
+ case animations::AnimationAdditiveMode::BASE:
+ // FALTHROUGH intended
+ case animations::AnimationAdditiveMode::REPLACE:
+ // TODO(F2): reverse-engineer the semantics of these
+ // values
+
+ // currently, treat them the same and replace
+ // the child value by our own
+ return rCurrValue;
+
+ case animations::AnimationAdditiveMode::SUM:
+ return rCurrValue + ((*mpChild).*pGetValue)();
+
+ case animations::AnimationAdditiveMode::MULTIPLY:
+ return rCurrValue * ((*mpChild).*pGetValue)();
+ }
+ }
+ else
+ {
+ // this object is the only one defining
+ // the value, so take it
+ return rCurrValue;
+ }
+ }
+ else
+ {
+ return bChildInstanceValueValid ?
+ ((*mpChild).*pGetValue)() :
+ T(); // pass on child value, regardless
+ // if it's valid or not. If not, it's
+ // a default anyway
+ }
+ }
+
+ ShapeAttributeLayer::ShapeAttributeLayer( const ShapeAttributeLayerSharedPtr& rChildLayer ) :
+ mpChild( rChildLayer ),
+
+ maSize(),
+ maPosition(),
+ maClip(),
+
+ maFontFamily(),
+
+ mnRotationAngle(),
+ mnShearXAngle(),
+ mnShearYAngle(),
+ mnAlpha(),
+ mnCharRotationAngle(),
+ mnCharScale(),
+ mnCharWeight(),
+
+ meFillStyle( drawing::FillStyle_NONE ),
+ meLineStyle( drawing::LineStyle_NONE ),
+ meCharPosture( awt::FontSlant_NONE ),
+ mnUnderlineMode(),
+
+ maDimColor(),
+ maFillColor(),
+ maLineColor(),
+ maCharColor(),
+
+ mnTransformationState( rChildLayer ? rChildLayer->getTransformationState() : 0 ),
+ mnClipState( rChildLayer ? rChildLayer->getClipState() : 0),
+ mnAlphaState( rChildLayer ? rChildLayer->getAlphaState() : 0),
+ mnPositionState( rChildLayer ? rChildLayer->getPositionState() : 0 ),
+ mnContentState( rChildLayer ? rChildLayer->getContentState() : 0 ),
+ mnVisibilityState( rChildLayer ? rChildLayer->getVisibilityState() : 0 ),
+
+ mnAdditiveMode( animations::AnimationAdditiveMode::BASE ),
+
+ mbVisibility( false ),
+
+ mbWidthValid( false ),
+ mbHeightValid( false ),
+ mbPosXValid( false ),
+ mbPosYValid( false ),
+ mbClipValid( false ),
+
+ mbFontFamilyValid( false ),
+
+ mbRotationAngleValid( false ),
+ mbShearXAngleValid( false ),
+ mbShearYAngleValid( false ),
+
+ mbAlphaValid( false ),
+
+ mbCharRotationAngleValid( false ),
+ mbCharScaleValid( false ),
+
+ mbDimColorValid( false ),
+ mbFillColorValid( false ),
+ mbLineColorValid( false ),
+ mbCharColorValid( false ),
+
+ mbFillStyleValid( false ),
+ mbLineStyleValid( false ),
+ mbCharWeightValid( false ),
+ mbUnderlineModeValid( false ),
+ mbCharPostureValid( false ),
+ mbVisibilityValid( false )
+ {
+ }
+
+ bool ShapeAttributeLayer::revokeChildLayer( const ShapeAttributeLayerSharedPtr& rChildLayer )
+ {
+ ENSURE_OR_RETURN_FALSE( rChildLayer,
+ "ShapeAttributeLayer::revokeChildLayer(): Will not remove NULL child" );
+
+ if( !haveChild() )
+ return false; // no children, nothing to revoke.
+
+ if( mpChild == rChildLayer )
+ {
+ // we have it - replace by removed child's sibling.
+ mpChild = rChildLayer->getChildLayer();
+
+ // if we're now the first one, defensively increment _all_
+ // state ids: possibly all underlying attributes have now
+ // changed to default
+ if( !haveChild() )
+ {
+ // TODO(P1): Check whether it pays off to check more
+ // detailed, which attributes really change
+ ++mnTransformationState;
+ ++mnClipState;
+ ++mnAlphaState;
+ ++mnPositionState;
+ ++mnContentState;
+ ++mnVisibilityState;
+ }
+ }
+ else
+ {
+ // we don't have it - pass on the request
+ if( !mpChild->revokeChildLayer( rChildLayer ) )
+ return false; // nobody has it - bail out
+ }
+
+ // something might have changed - update ids.
+ updateStateIds();
+
+ return true;
+ }
+
+ ShapeAttributeLayerSharedPtr ShapeAttributeLayer::getChildLayer() const
+ {
+ return mpChild;
+ }
+
+ void ShapeAttributeLayer::setAdditiveMode( sal_Int16 nMode )
+ {
+ if( mnAdditiveMode != nMode )
+ {
+ // TODO(P1): Check whether it pays off to check more
+ // detailed, which attributes really change
+
+ // defensively increment all states - possibly each of them
+ // will change with different additive mode
+ ++mnTransformationState;
+ ++mnClipState;
+ ++mnAlphaState;
+ ++mnPositionState;
+ ++mnContentState;
+ ++mnVisibilityState;
+ }
+
+ mnAdditiveMode = nMode;
+ }
+
+ bool ShapeAttributeLayer::isWidthValid() const
+ {
+ return mbWidthValid ? true : haveChild() ? mpChild->isWidthValid() : false;
+ }
+
+ double ShapeAttributeLayer::getWidth() const
+ {
+ return calcValue< double >(
+ maSize.getX(),
+ mbWidthValid,
+ &ShapeAttributeLayer::isWidthValid,
+ &ShapeAttributeLayer::getWidth );
+ }
+
+ void ShapeAttributeLayer::setWidth( const double& rNewWidth )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewWidth),
+ "ShapeAttributeLayer::setWidth(): Invalid width" );
+
+ maSize.setX( rNewWidth );
+ mbWidthValid = true;
+ ++mnTransformationState;
+ }
+
+ bool ShapeAttributeLayer::isHeightValid() const
+ {
+ return mbHeightValid ? true : haveChild() ? mpChild->isHeightValid() : false;
+ }
+
+ double ShapeAttributeLayer::getHeight() const
+ {
+ return calcValue< double >(
+ maSize.getY(),
+ mbHeightValid,
+ &ShapeAttributeLayer::isHeightValid,
+ &ShapeAttributeLayer::getHeight );
+ }
+
+ void ShapeAttributeLayer::setHeight( const double& rNewHeight )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewHeight),
+ "ShapeAttributeLayer::setHeight(): Invalid height" );
+
+ maSize.setY( rNewHeight );
+ mbHeightValid = true;
+ ++mnTransformationState;
+ }
+
+ void ShapeAttributeLayer::setSize( const ::basegfx::B2DSize& rNewSize )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewSize.getX()) &&
+ ::rtl::math::isFinite(rNewSize.getY()),
+ "ShapeAttributeLayer::setSize(): Invalid size" );
+
+ maSize = rNewSize;
+ mbWidthValid = mbHeightValid = true;
+ ++mnTransformationState;
+ }
+
+ bool ShapeAttributeLayer::isPosXValid() const
+ {
+ return mbPosXValid ? true : haveChild() ? mpChild->isPosXValid() : false;
+ }
+
+ double ShapeAttributeLayer::getPosX() const
+ {
+ return calcValue< double >(
+ maPosition.getX(),
+ mbPosXValid,
+ &ShapeAttributeLayer::isPosXValid,
+ &ShapeAttributeLayer::getPosX );
+ }
+
+ void ShapeAttributeLayer::setPosX( const double& rNewX )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewX),
+ "ShapeAttributeLayer::setPosX(): Invalid position" );
+
+ maPosition.setX( rNewX );
+ mbPosXValid = true;
+ ++mnPositionState;
+ }
+
+ bool ShapeAttributeLayer::isPosYValid() const
+ {
+ return mbPosYValid ? true : haveChild() ? mpChild->isPosYValid() : false;
+ }
+
+ double ShapeAttributeLayer::getPosY() const
+ {
+ return calcValue< double >(
+ maPosition.getY(),
+ mbPosYValid,
+ &ShapeAttributeLayer::isPosYValid,
+ &ShapeAttributeLayer::getPosY );
+ }
+
+ void ShapeAttributeLayer::setPosY( const double& rNewY )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewY),
+ "ShapeAttributeLayer::setPosY(): Invalid position" );
+
+ maPosition.setY( rNewY );
+ mbPosYValid = true;
+ ++mnPositionState;
+ }
+
+ void ShapeAttributeLayer::setPosition( const ::basegfx::B2DPoint& rNewPos )
+ {
+ maPosition = rNewPos;
+ mbPosXValid = mbPosYValid = true;
+ ++mnPositionState;
+ }
+
+ bool ShapeAttributeLayer::isRotationAngleValid() const
+ {
+ return mbRotationAngleValid ? true : haveChild() ? mpChild->isRotationAngleValid() : false;
+ }
+
+ double ShapeAttributeLayer::getRotationAngle() const
+ {
+ return calcValue< double >(
+ mnRotationAngle,
+ mbRotationAngleValid,
+ &ShapeAttributeLayer::isRotationAngleValid,
+ &ShapeAttributeLayer::getRotationAngle );
+ }
+
+ void ShapeAttributeLayer::setRotationAngle( const double& rNewAngle )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
+ "ShapeAttributeLayer::setRotationAngle(): Invalid angle" );
+
+ mnRotationAngle = rNewAngle;
+ mbRotationAngleValid = true;
+ ++mnTransformationState;
+ }
+
+ bool ShapeAttributeLayer::isShearXAngleValid() const
+ {
+ return mbShearXAngleValid ? true : haveChild() ? mpChild->isShearXAngleValid() : false;
+ }
+
+ double ShapeAttributeLayer::getShearXAngle() const
+ {
+ return calcValue( mnShearXAngle,
+ mbShearXAngleValid,
+ &ShapeAttributeLayer::isShearXAngleValid,
+ &ShapeAttributeLayer::getShearXAngle );
+ }
+
+ void ShapeAttributeLayer::setShearXAngle( const double& rNewAngle )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
+ "ShapeAttributeLayer::setShearXAngle(): Invalid angle" );
+
+ mnShearXAngle = rNewAngle;
+ mbShearXAngleValid = true;
+ ++mnTransformationState;
+ }
+
+ bool ShapeAttributeLayer::isShearYAngleValid() const
+ {
+ return mbShearYAngleValid ? true : haveChild() ? mpChild->isShearYAngleValid() : false;
+ }
+
+ double ShapeAttributeLayer::getShearYAngle() const
+ {
+ return calcValue( mnShearYAngle,
+ mbShearYAngleValid,
+ &ShapeAttributeLayer::isShearYAngleValid,
+ &ShapeAttributeLayer::getShearYAngle );
+ }
+
+ void ShapeAttributeLayer::setShearYAngle( const double& rNewAngle )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
+ "ShapeAttributeLayer::setShearYAngle(): Invalid angle" );
+
+ mnShearYAngle = rNewAngle;
+ mbShearYAngleValid = true;
+ ++mnTransformationState;
+ }
+
+ bool ShapeAttributeLayer::isAlphaValid() const
+ {
+ return mbAlphaValid ? true : haveChild() ? mpChild->isAlphaValid() : false;
+ }
+
+ double ShapeAttributeLayer::getAlpha() const
+ {
+ return calcValue( mnAlpha,
+ mbAlphaValid,
+ &ShapeAttributeLayer::isAlphaValid,
+ &ShapeAttributeLayer::getAlpha );
+ }
+
+ void ShapeAttributeLayer::setAlpha( const double& rNewValue )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewValue),
+ "ShapeAttributeLayer::setAlpha(): Invalid alpha" );
+
+ mnAlpha = rNewValue;
+ mbAlphaValid = true;
+ ++mnAlphaState;
+ }
+
+ bool ShapeAttributeLayer::isClipValid() const
+ {
+ return mbClipValid ? true : haveChild() ? mpChild->isClipValid() : false;
+ }
+
+ ::basegfx::B2DPolyPolygon ShapeAttributeLayer::getClip() const
+ {
+ // TODO(F1): Implement polygon algebra for additive modes
+ if( mbClipValid )
+ return maClip;
+ else if( haveChild() )
+ return mpChild->getClip();
+ else
+ return ::basegfx::B2DPolyPolygon();
+ }
+
+ void ShapeAttributeLayer::setClip( const ::basegfx::B2DPolyPolygon& rNewClip )
+ {
+ maClip = rNewClip;
+ mbClipValid = true;
+ ++mnClipState;
+ }
+
+ bool ShapeAttributeLayer::isDimColorValid() const
+ {
+ return mbDimColorValid ? true : haveChild() ? mpChild->isDimColorValid() : false;
+ }
+
+ RGBColor ShapeAttributeLayer::getDimColor() const
+ {
+ return calcValue( maDimColor,
+ mbDimColorValid,
+ &ShapeAttributeLayer::isDimColorValid,
+ &ShapeAttributeLayer::getDimColor );
+ }
+
+ void ShapeAttributeLayer::setDimColor( const RGBColor& nNewColor )
+ {
+ maDimColor = nNewColor;
+ mbDimColorValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isFillColorValid() const
+ {
+ return mbFillColorValid ? true : haveChild() ? mpChild->isFillColorValid() : false;
+ }
+
+ RGBColor ShapeAttributeLayer::getFillColor() const
+ {
+ return calcValue( maFillColor,
+ mbFillColorValid,
+ &ShapeAttributeLayer::isFillColorValid,
+ &ShapeAttributeLayer::getFillColor );
+ }
+
+ void ShapeAttributeLayer::setFillColor( const RGBColor& nNewColor )
+ {
+ maFillColor = nNewColor;
+ mbFillColorValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isLineColorValid() const
+ {
+ return mbLineColorValid ? true : haveChild() ? mpChild->isLineColorValid() : false;
+ }
+
+ RGBColor ShapeAttributeLayer::getLineColor() const
+ {
+ return calcValue( maLineColor,
+ mbLineColorValid,
+ &ShapeAttributeLayer::isLineColorValid,
+ &ShapeAttributeLayer::getLineColor );
+ }
+
+ void ShapeAttributeLayer::setLineColor( const RGBColor& nNewColor )
+ {
+ maLineColor = nNewColor;
+ mbLineColorValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isFillStyleValid() const
+ {
+ return mbFillStyleValid ? true : haveChild() ? mpChild->isFillStyleValid() : false;
+ }
+
+ sal_Int16 ShapeAttributeLayer::getFillStyle() const
+ {
+ // mnAdditiveMode is ignored, cannot combine strings in
+ // any sensible way
+ if( mbFillStyleValid )
+ return sal::static_int_cast<sal_Int16>(meFillStyle);
+ else if( haveChild() )
+ return sal::static_int_cast<sal_Int16>(mpChild->getFillStyle());
+ else
+ return sal::static_int_cast<sal_Int16>(drawing::FillStyle_SOLID);
+ }
+
+ void ShapeAttributeLayer::setFillStyle( const sal_Int16& rStyle )
+ {
+ // TODO(Q1): Check range here.
+ meFillStyle = (drawing::FillStyle)rStyle;
+ mbFillStyleValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isLineStyleValid() const
+ {
+ return mbLineStyleValid ? true : haveChild() ? mpChild->isLineStyleValid() : false;
+ }
+
+ sal_Int16 ShapeAttributeLayer::getLineStyle() const
+ {
+ // mnAdditiveMode is ignored, cannot combine strings in
+ // any sensible way
+ if( mbLineStyleValid )
+ return sal::static_int_cast<sal_Int16>(meLineStyle);
+ else if( haveChild() )
+ return sal::static_int_cast<sal_Int16>(mpChild->getLineStyle());
+ else
+ return sal::static_int_cast<sal_Int16>(drawing::LineStyle_SOLID);
+ }
+
+ void ShapeAttributeLayer::setLineStyle( const sal_Int16& rStyle )
+ {
+ // TODO(Q1): Check range here.
+ meLineStyle = (drawing::LineStyle)rStyle;
+ mbLineStyleValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isVisibilityValid() const
+ {
+ return mbVisibilityValid ? true : haveChild() ? mpChild->isVisibilityValid() : false;
+ }
+
+ bool ShapeAttributeLayer::getVisibility() const
+ {
+ // mnAdditiveMode is ignored, SMIL spec requires to not combine
+ // bools in any sensible way
+ if( mbVisibilityValid )
+ return mbVisibility;
+ else if( haveChild() )
+ return mpChild->getVisibility();
+ else
+ return true; // default is always visible
+ }
+
+ void ShapeAttributeLayer::setVisibility( const bool& bVisible )
+ {
+ mbVisibility = bVisible;
+ mbVisibilityValid = true;
+ ++mnVisibilityState;
+ }
+
+ bool ShapeAttributeLayer::isCharColorValid() const
+ {
+ return mbCharColorValid ? true : haveChild() ? mpChild->isCharColorValid() : false;
+ }
+
+ RGBColor ShapeAttributeLayer::getCharColor() const
+ {
+ return calcValue( maCharColor,
+ mbCharColorValid,
+ &ShapeAttributeLayer::isCharColorValid,
+ &ShapeAttributeLayer::getCharColor );
+ }
+
+ void ShapeAttributeLayer::setCharColor( const RGBColor& nNewColor )
+ {
+ maCharColor = nNewColor;
+ mbCharColorValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isCharRotationAngleValid() const
+ {
+ return mbCharRotationAngleValid ? true : haveChild() ? mpChild->isCharRotationAngleValid() : false;
+ }
+
+ double ShapeAttributeLayer::getCharRotationAngle() const
+ {
+ return calcValue( mnCharRotationAngle,
+ mbCharRotationAngleValid,
+ &ShapeAttributeLayer::isCharRotationAngleValid,
+ &ShapeAttributeLayer::getCharRotationAngle );
+ }
+
+ void ShapeAttributeLayer::setCharRotationAngle( const double& rNewAngle )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewAngle),
+ "ShapeAttributeLayer::setCharRotationAngle(): Invalid angle" );
+
+ mnCharRotationAngle = rNewAngle;
+ mbCharRotationAngleValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isCharWeightValid() const
+ {
+ return mbCharWeightValid ? true : haveChild() ? mpChild->isCharWeightValid() : false;
+ }
+
+ double ShapeAttributeLayer::getCharWeight() const
+ {
+ // mnAdditiveMode is ignored, cannot combine strings in
+ // any sensible way
+ if( mbCharWeightValid )
+ return mnCharWeight;
+ else if( haveChild() )
+ return mpChild->getCharWeight();
+ else
+ return awt::FontWeight::NORMAL;
+ }
+
+ void ShapeAttributeLayer::setCharWeight( const double& rValue )
+ {
+ // TODO(Q1): Check range here.
+ mnCharWeight = rValue;
+ mbCharWeightValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isUnderlineModeValid() const
+ {
+ return mbUnderlineModeValid ? true : haveChild() ? mpChild->isUnderlineModeValid() : false;
+ }
+
+ sal_Int16 ShapeAttributeLayer::getUnderlineMode() const
+ {
+ // mnAdditiveMode is ignored, SMIL spec requires to not combine
+ // bools in any sensible way
+ if( mbUnderlineModeValid )
+ return mnUnderlineMode;
+ else if( haveChild() )
+ return mpChild->getUnderlineMode();
+ else
+ return awt::FontUnderline::NONE; // default is no underline
+ }
+
+ void ShapeAttributeLayer::setUnderlineMode( const sal_Int16& rUnderlineMode )
+ {
+ // TODO(Q1): Check range here.
+ mnUnderlineMode = rUnderlineMode;
+ mbUnderlineModeValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isFontFamilyValid() const
+ {
+ return mbFontFamilyValid ? true : haveChild() ? mpChild->isFontFamilyValid() : false;
+ }
+
+ ::rtl::OUString ShapeAttributeLayer::getFontFamily() const
+ {
+ // mnAdditiveMode is ignored, cannot combine strings in
+ // any sensible way
+ if( mbFontFamilyValid )
+ return maFontFamily;
+ else if( haveChild() )
+ return mpChild->getFontFamily();
+ else
+ return ::rtl::OUString();
+ }
+
+ void ShapeAttributeLayer::setFontFamily( const ::rtl::OUString& rName )
+ {
+ maFontFamily = rName;
+ mbFontFamilyValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isCharPostureValid() const
+ {
+ return mbCharPostureValid ? true : haveChild() ? mpChild->isCharPostureValid() : false;
+ }
+
+ sal_Int16 ShapeAttributeLayer::getCharPosture() const
+ {
+ // mnAdditiveMode is ignored, cannot combine strings in
+ // any sensible way
+ if( mbCharPostureValid )
+ return sal::static_int_cast<sal_Int16>(meCharPosture);
+ else if( haveChild() )
+ return sal::static_int_cast<sal_Int16>(mpChild->getCharPosture());
+ else
+ return sal::static_int_cast<sal_Int16>(awt::FontSlant_NONE);
+ }
+
+ void ShapeAttributeLayer::setCharPosture( const sal_Int16& rStyle )
+ {
+ // TODO(Q1): Check range here.
+ meCharPosture = (awt::FontSlant)rStyle;
+ mbCharPostureValid = true;
+ ++mnContentState;
+ }
+
+ bool ShapeAttributeLayer::isCharScaleValid() const
+ {
+ return mbCharScaleValid ? true : haveChild() ? mpChild->isCharScaleValid() : false;
+ }
+
+ double ShapeAttributeLayer::getCharScale() const
+ {
+ return calcValue( mnCharScale,
+ mbCharScaleValid,
+ &ShapeAttributeLayer::isCharScaleValid,
+ &ShapeAttributeLayer::getCharScale );
+ }
+
+ void ShapeAttributeLayer::setCharScale( const double& rNewHeight )
+ {
+ ENSURE_OR_THROW( ::rtl::math::isFinite(rNewHeight),
+ "ShapeAttributeLayer::setCharScale(): Invalid height" );
+
+ mnCharScale = rNewHeight;
+ mbCharScaleValid = true;
+ ++mnContentState;
+ }
+
+ State::StateId ShapeAttributeLayer::getTransformationState() const
+ {
+ return haveChild() ?
+ ::std::max( mnTransformationState,
+ mpChild->getTransformationState() ) :
+ mnTransformationState;
+ }
+
+ State::StateId ShapeAttributeLayer::getClipState() const
+ {
+ return haveChild() ?
+ ::std::max( mnClipState,
+ mpChild->getClipState() ) :
+ mnClipState;
+ }
+
+ State::StateId ShapeAttributeLayer::getAlphaState() const
+ {
+ return haveChild() ?
+ ::std::max( mnAlphaState,
+ mpChild->getAlphaState() ) :
+ mnAlphaState;
+ }
+
+ State::StateId ShapeAttributeLayer::getPositionState() const
+ {
+ return haveChild() ?
+ ::std::max( mnPositionState,
+ mpChild->getPositionState() ) :
+ mnPositionState;
+ }
+
+ State::StateId ShapeAttributeLayer::getContentState() const
+ {
+ return haveChild() ?
+ ::std::max( mnContentState,
+ mpChild->getContentState() ) :
+ mnContentState;
+ }
+
+ State::StateId ShapeAttributeLayer::getVisibilityState() const
+ {
+ return haveChild() ?
+ ::std::max( mnVisibilityState,
+ mpChild->getVisibilityState() ) :
+ mnVisibilityState;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/appletshape.cxx b/slideshow/source/engine/shapes/appletshape.cxx
new file mode 100644
index 000000000000..f998e6df704e
--- /dev/null
+++ b/slideshow/source/engine/shapes/appletshape.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <boost/shared_ptr.hpp>
+
+#include "appletshape.hxx"
+#include "externalshapebase.hxx"
+#include "vieweventhandler.hxx"
+#include "viewappletshape.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Represents an applet shape.
+
+ This implementation offers support for applet shapes (both
+ Java applets, and Netscape plugins). Such shapes need
+ special treatment.
+ */
+ class AppletShape : public ExternalShapeBase
+ {
+ public:
+ /** Create a shape for the given XShape for a applet object
+
+ @param xShape
+ The XShape to represent.
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+
+ @param rServiceName
+ Service name to use, when creating the actual viewer
+ component
+
+ @param pPropCopyTable
+ Table of plain ASCII property names, to copy from
+ xShape to applet.
+
+ @param nNumPropEntries
+ Number of property table entries (in pPropCopyTable)
+ */
+ AppletShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ double nPrio,
+ const ::rtl::OUString& rServiceName,
+ const char** pPropCopyTable,
+ sal_Size nNumPropEntries,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ private:
+
+ // View layer methods
+ //------------------------------------------------------------------
+
+ virtual void addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer );
+ virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer );
+ virtual bool clearAllViewLayers();
+
+
+ // ExternalShapeBase methods
+ //------------------------------------------------------------------
+
+ virtual bool implRender( const ::basegfx::B2DRange& rCurrBounds ) const;
+ virtual void implViewChanged( const UnoViewSharedPtr& rView );
+ virtual void implViewsChanged();
+ virtual bool implStartIntrinsicAnimation();
+ virtual bool implEndIntrinsicAnimation();
+ virtual bool implPauseIntrinsicAnimation();
+ virtual bool implIsIntrinsicAnimationPlaying() const;
+ virtual void implSetIntrinsicAnimationTime(double);
+
+ const ::rtl::OUString maServiceName;
+ const char** mpPropCopyTable;
+ const sal_Size mnNumPropEntries;
+
+ /// the list of active view shapes (one for each registered view layer)
+ typedef ::std::vector< ViewAppletShapeSharedPtr > ViewAppletShapeVector;
+ ViewAppletShapeVector maViewAppletShapes;
+ bool mbIsPlaying;
+ };
+
+ AppletShape::AppletShape( const uno::Reference< drawing::XShape >& xShape,
+ double nPrio,
+ const ::rtl::OUString& rServiceName,
+ const char** pPropCopyTable,
+ sal_Size nNumPropEntries,
+ const SlideShowContext& rContext ) :
+ ExternalShapeBase( xShape, nPrio, rContext ),
+ maServiceName( rServiceName ),
+ mpPropCopyTable( pPropCopyTable ),
+ mnNumPropEntries( nNumPropEntries ),
+ maViewAppletShapes(),
+ mbIsPlaying(false)
+ {
+ }
+
+ // ---------------------------------------------------------------------
+
+ void AppletShape::implViewChanged( const UnoViewSharedPtr& rView )
+ {
+ // determine ViewAppletShape that needs update
+ ViewAppletShapeVector::const_iterator aIter(maViewAppletShapes.begin());
+ ViewAppletShapeVector::const_iterator const aEnd (maViewAppletShapes.end());
+ while( aIter != aEnd )
+ {
+ if( (*aIter)->getViewLayer()->isOnView(rView) )
+ (*aIter)->resize(getBounds());
+
+ ++aIter;
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ void AppletShape::implViewsChanged()
+ {
+ // resize all ViewShapes
+ ::std::for_each( maViewAppletShapes.begin(),
+ maViewAppletShapes.end(),
+ ::boost::bind(
+ &ViewAppletShape::resize,
+ _1,
+ ::boost::cref( AppletShape::getBounds())) );
+ }
+
+ // ---------------------------------------------------------------------
+
+ void AppletShape::addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer )
+ {
+ try
+ {
+ maViewAppletShapes.push_back(
+ ViewAppletShapeSharedPtr( new ViewAppletShape( rNewLayer,
+ getXShape(),
+ maServiceName,
+ mpPropCopyTable,
+ mnNumPropEntries,
+ mxComponentContext )));
+
+ // push new size to view shape
+ maViewAppletShapes.back()->resize( getBounds() );
+
+ // render the Shape on the newly added ViewLayer
+ if( bRedrawLayer )
+ maViewAppletShapes.back()->render( getBounds() );
+ }
+ catch(uno::Exception&)
+ {
+ // ignore failed shapes - slideshow should run with
+ // the remaining content
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
+ {
+ const ViewAppletShapeVector::iterator aEnd( maViewAppletShapes.end() );
+
+ OSL_ENSURE( ::std::count_if(maViewAppletShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewAppletShape::getViewLayer, _1 ),
+ ::boost::cref( rLayer ) ) ) < 2,
+ "AppletShape::removeViewLayer(): Duplicate ViewLayer entries!" );
+
+ ViewAppletShapeVector::iterator aIter;
+
+ if( (aIter=::std::remove_if( maViewAppletShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewAppletShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rLayer ) ) )) == aEnd )
+ {
+ // view layer seemingly was not added, failed
+ return false;
+ }
+
+ // actually erase from container
+ maViewAppletShapes.erase( aIter, aEnd );
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::clearAllViewLayers()
+ {
+ maViewAppletShapes.clear();
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::implRender( const ::basegfx::B2DRange& rCurrBounds ) const
+ {
+ // redraw all view shapes, by calling their update() method
+ if( ::std::count_if( maViewAppletShapes.begin(),
+ maViewAppletShapes.end(),
+ ::boost::bind<bool>(
+ ::boost::mem_fn( &ViewAppletShape::render ),
+ _1,
+ ::boost::cref( rCurrBounds ) ) )
+ != static_cast<ViewAppletShapeVector::difference_type>(maViewAppletShapes.size()) )
+ {
+ // at least one of the ViewShape::update() calls did return
+ // false - update failed on at least one ViewLayer
+ return false;
+ }
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::implStartIntrinsicAnimation()
+ {
+ ::std::for_each( maViewAppletShapes.begin(),
+ maViewAppletShapes.end(),
+ ::boost::bind( &ViewAppletShape::startApplet,
+ _1,
+ ::boost::cref( getBounds() )));
+ mbIsPlaying = true;
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::implEndIntrinsicAnimation()
+ {
+ ::std::for_each( maViewAppletShapes.begin(),
+ maViewAppletShapes.end(),
+ ::boost::mem_fn( &ViewAppletShape::endApplet ) );
+
+ mbIsPlaying = false;
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::implPauseIntrinsicAnimation()
+ {
+ // TODO(F1): any way of temporarily disabling/deactivating
+ // applets?
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool AppletShape::implIsIntrinsicAnimationPlaying() const
+ {
+ return mbIsPlaying;
+ }
+
+ // ---------------------------------------------------------------------
+
+ void AppletShape::implSetIntrinsicAnimationTime(double)
+ {
+ // No way of doing this, or?
+ }
+
+ boost::shared_ptr<Shape> createAppletShape(
+ const uno::Reference< drawing::XShape >& xShape,
+ double nPrio,
+ const ::rtl::OUString& rServiceName,
+ const char** pPropCopyTable,
+ sal_Size nNumPropEntries,
+ const SlideShowContext& rContext )
+ {
+ boost::shared_ptr< AppletShape > pAppletShape(
+ new AppletShape(xShape,
+ nPrio,
+ rServiceName,
+ pPropCopyTable,
+ nNumPropEntries,
+ rContext) );
+
+ return pAppletShape;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/appletshape.hxx b/slideshow/source/engine/shapes/appletshape.hxx
new file mode 100644
index 000000000000..4eb86ee2e378
--- /dev/null
+++ b/slideshow/source/engine/shapes/appletshape.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_APPLETSHAPE_HXX
+#define INCLUDED_SLIDESHOW_APPLETSHAPE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ class XShape;
+} } } }
+namespace rtl {
+ class OUString;
+}
+
+namespace slideshow
+{
+ namespace internal
+ {
+ struct SlideShowContext;
+ class Shape;
+
+ boost::shared_ptr<Shape> createAppletShape(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ double nPrio,
+ const ::rtl::OUString& rServiceName,
+ const char** pPropCopyTable,
+ sal_Size nNumPropEntries,
+ const SlideShowContext& rContext );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_APPLETSHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/backgroundshape.cxx b/slideshow/source/engine/shapes/backgroundshape.cxx
new file mode 100644
index 000000000000..4f46d9172fb2
--- /dev/null
+++ b/slideshow/source/engine/shapes/backgroundshape.cxx
@@ -0,0 +1,339 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <rtl/logfile.hxx>
+
+#include <vcl/metaact.hxx>
+#include <vcl/gdimtf.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/bind.hpp>
+
+#include <cmath> // for trigonometry and fabs
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+#include "backgroundshape.hxx"
+#include "slideshowexceptions.hxx"
+#include "slideshowcontext.hxx"
+#include "gdimtftools.hxx"
+#include "shape.hxx"
+#include "viewbackgroundshape.hxx"
+
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Representation of a draw document's background shape.
+
+ This class implements the Shape interface for the
+ background shape. Since the background shape is neither
+ animatable nor attributable, those more specialized
+ derivations of the Shape interface are not implemented
+ here.
+
+ @attention this class is to be treated 'final', i.e. one
+ should not derive from it.
+ */
+ class BackgroundShape : public Shape
+ {
+ public:
+ /** Create the background shape.
+
+ This method creates a shape that handles the
+ peculiarities of the draw API regarding background
+ content.
+ */
+ BackgroundShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xDrawPage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xMasterPage,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > getXShape() const;
+
+ // View layer methods
+ //------------------------------------------------------------------
+
+ virtual void addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer );
+ virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer );
+ virtual bool clearAllViewLayers();
+
+
+ // attribute methods
+ //------------------------------------------------------------------
+
+ virtual ::basegfx::B2DRectangle getBounds() const;
+ virtual ::basegfx::B2DRectangle getDomBounds() const;
+ virtual ::basegfx::B2DRectangle getUpdateArea() const;
+ virtual bool isVisible() const;
+ virtual double getPriority() const;
+ virtual bool isBackgroundDetached() const;
+
+
+ // render methods
+ //------------------------------------------------------------------
+
+ virtual bool update() const;
+ virtual bool render() const;
+ virtual bool isContentChanged() const;
+
+ private:
+ /// The metafile actually representing the Shape
+ GDIMetaFileSharedPtr mpMtf;
+
+ // The attributes of this Shape
+ ::basegfx::B2DRectangle maBounds; // always needed for rendering
+
+ /// the list of active view shapes (one for each registered view layer)
+ typedef ::std::vector< ViewBackgroundShapeSharedPtr > ViewBackgroundShapeVector;
+ ViewBackgroundShapeVector maViewShapes;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ BackgroundShape::BackgroundShape( const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const uno::Reference< drawing::XDrawPage >& xMasterPage,
+ const SlideShowContext& rContext ) :
+ mpMtf(),
+ maBounds(),
+ maViewShapes()
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
+ uno::UNO_QUERY_THROW );
+ GDIMetaFileSharedPtr pMtf( new GDIMetaFile() );
+
+ // first try the page background (overrides
+ // masterpage background), then try masterpage
+ if( !getMetaFile( uno::Reference<lang::XComponent>(xDrawPage, uno::UNO_QUERY),
+ xDrawPage, *pMtf, MTF_LOAD_BACKGROUND_ONLY,
+ rContext.mxComponentContext ) &&
+ !getMetaFile( uno::Reference<lang::XComponent>(xMasterPage, uno::UNO_QUERY),
+ xDrawPage, *pMtf, MTF_LOAD_BACKGROUND_ONLY,
+ rContext.mxComponentContext ))
+ {
+ throw ShapeLoadFailedException();
+ }
+
+ // there is a special background shape, add it
+ // as the first one
+ // ---------------------------------------------------
+
+ sal_Int32 nDocWidth=0;
+ sal_Int32 nDocHeight=0;
+ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= nDocWidth;
+ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= nDocHeight;
+
+ mpMtf = pMtf;
+ maBounds = ::basegfx::B2DRectangle( 0,0,nDocWidth, nDocHeight );
+ }
+
+ uno::Reference< drawing::XShape > BackgroundShape::getXShape() const
+ {
+ // no real XShape representative
+ return uno::Reference< drawing::XShape >();
+ }
+
+ void BackgroundShape::addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer )
+ {
+ ViewBackgroundShapeVector::iterator aEnd( maViewShapes.end() );
+
+ // already added?
+ if( ::std::find_if( maViewShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewBackgroundShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rNewLayer ) ) ) != aEnd )
+ {
+ // yes, nothing to do
+ return;
+ }
+
+ maViewShapes.push_back(
+ ViewBackgroundShapeSharedPtr(
+ new ViewBackgroundShape( rNewLayer,
+ maBounds ) ) );
+
+ // render the Shape on the newly added ViewLayer
+ if( bRedrawLayer )
+ maViewShapes.back()->render( mpMtf );
+ }
+
+ bool BackgroundShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
+ {
+ const ViewBackgroundShapeVector::iterator aEnd( maViewShapes.end() );
+
+ OSL_ENSURE( ::std::count_if(maViewShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewBackgroundShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rLayer ) ) ) < 2,
+ "BackgroundShape::removeViewLayer(): Duplicate ViewLayer entries!" );
+
+ ViewBackgroundShapeVector::iterator aIter;
+
+ if( (aIter=::std::remove_if( maViewShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewBackgroundShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rLayer ) ) )) == aEnd )
+ {
+ // view layer seemingly was not added, failed
+ return false;
+ }
+
+ // actually erase from container
+ maViewShapes.erase( aIter, aEnd );
+
+ return true;
+ }
+
+ bool BackgroundShape::clearAllViewLayers()
+ {
+ maViewShapes.clear();
+ return true;
+ }
+
+ ::basegfx::B2DRectangle BackgroundShape::getBounds() const
+ {
+ return maBounds;
+ }
+
+ ::basegfx::B2DRectangle BackgroundShape::getDomBounds() const
+ {
+ return maBounds;
+ }
+
+ ::basegfx::B2DRectangle BackgroundShape::getUpdateArea() const
+ {
+ // TODO(F1): Need to expand background, too, when
+ // antialiasing?
+
+ // no transformation etc. possible for background shape
+ return maBounds;
+ }
+
+ bool BackgroundShape::isVisible() const
+ {
+ return true;
+ }
+
+ double BackgroundShape::getPriority() const
+ {
+ return 0.0; // lowest prio, we're the background
+ }
+
+ bool BackgroundShape::update() const
+ {
+ return render();
+ }
+
+ bool BackgroundShape::render() const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::BackgroundShape::render()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::presentation::internal::BackgroundShape: 0x%X", this );
+
+ // gcc again...
+ const ::basegfx::B2DRectangle& rCurrBounds( BackgroundShape::getBounds() );
+
+ if( rCurrBounds.getRange().equalZero() )
+ {
+ // zero-sized shapes are effectively invisible,
+ // thus, we save us the rendering...
+ return true;
+ }
+
+ // redraw all view shapes, by calling their render() method
+ if( ::std::count_if( maViewShapes.begin(),
+ maViewShapes.end(),
+ ::boost::bind( &ViewBackgroundShape::render,
+ _1,
+ ::boost::cref( mpMtf ) ) )
+ != static_cast<ViewBackgroundShapeVector::difference_type>(maViewShapes.size()) )
+ {
+ // at least one of the ViewBackgroundShape::render() calls did return
+ // false - update failed on at least one ViewLayer
+ return false;
+ }
+
+ return true;
+ }
+
+ bool BackgroundShape::isContentChanged() const
+ {
+ return false;
+ }
+
+ bool BackgroundShape::isBackgroundDetached() const
+ {
+ return false; // we're not animatable
+ }
+
+ //////////////////////////////////////////////////////////
+
+ ShapeSharedPtr createBackgroundShape(
+ const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const uno::Reference< drawing::XDrawPage >& xMasterPage,
+ const SlideShowContext& rContext )
+ {
+ return ShapeSharedPtr(
+ new BackgroundShape(
+ xDrawPage,
+ xMasterPage,
+ rContext ));
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/backgroundshape.hxx b/slideshow/source/engine/shapes/backgroundshape.hxx
new file mode 100644
index 000000000000..1de9eaa6e86b
--- /dev/null
+++ b/slideshow/source/engine/shapes/backgroundshape.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_BACKGROUNDSHAPE_HXX
+#define INCLUDED_SLIDESHOW_BACKGROUNDSHAPE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ class XDrawPage;
+} } } }
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class Shape;
+ struct SlideShowContext;
+
+ /** Representation of a draw document's background shape.
+
+ This function generates the Shape for the background
+ shape. Since the background shape is neither animatable
+ nor attributable, those more specialized derivations of
+ the Shape interface are not implemented here.
+ */
+ boost::shared_ptr<Shape> createBackgroundShape(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xDrawPage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xMasterPage,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_BACKGROUNDSHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawinglayeranimation.cxx b/slideshow/source/engine/shapes/drawinglayeranimation.cxx
new file mode 100644
index 000000000000..fdad9fd404d2
--- /dev/null
+++ b/slideshow/source/engine/shapes/drawinglayeranimation.cxx
@@ -0,0 +1,986 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/elapsedtime.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <rtl/math.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/salbtype.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/metaact.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/TextAnimationKind.hpp>
+#include <com/sun/star/drawing/TextAnimationDirection.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+
+#include "activity.hxx"
+#include "wakeupevent.hxx"
+#include "eventqueue.hxx"
+#include "drawshapesubsetting.hxx"
+#include "drawshape.hxx"
+#include "shapesubset.hxx"
+#include "shapeattributelayerholder.hxx"
+#include "slideshowcontext.hxx"
+#include "tools.hxx"
+#include "gdimtftools.hxx"
+#include "eventmultiplexer.hxx"
+#include "intrinsicanimationactivity.hxx"
+#include "intrinsicanimationeventhandler.hxx"
+
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/noncopyable.hpp>
+#include <vector>
+
+using namespace com::sun::star;
+using namespace ::slideshow::internal;
+
+namespace {
+
+class ScrollTextAnimNode
+{
+ sal_uInt32 mnDuration; // single duration
+ sal_uInt32 mnRepeat; // 0 -> endless
+ double mfStart;
+ double mfStop;
+ sal_uInt32 mnFrequency; // in ms
+ // forth and back change at mnRepeat%2:
+ bool mbAlternate;
+
+public:
+ ScrollTextAnimNode(
+ sal_uInt32 nDuration, sal_uInt32 nRepeat, double fStart, double fStop,
+ sal_uInt32 nFrequency, bool bAlternate)
+ : mnDuration(nDuration),
+ mnRepeat(nRepeat),
+ mfStart(fStart),
+ mfStop(fStop),
+ mnFrequency(nFrequency),
+ mbAlternate(bAlternate)
+ {}
+
+ sal_uInt32 GetDuration() const { return mnDuration; }
+ sal_uInt32 GetRepeat() const { return mnRepeat; }
+ sal_uInt32 GetFullTime() const { return mnDuration * mnRepeat; }
+ double GetStart() const { return mfStart; }
+ double GetStop() const { return mfStop; }
+ sal_uInt32 GetFrequency() const { return mnFrequency; }
+ bool DoAlternate() const { return mbAlternate; }
+
+ double GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const;
+};
+
+double ScrollTextAnimNode::GetStateAtRelativeTime(
+ sal_uInt32 nRelativeTime) const
+{
+ // #151174# Avoid division by zero.
+ if( mnDuration == 0 )
+ return mfStop;
+
+ if(mnRepeat)
+ {
+ // ending
+ const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
+ sal_uInt32 nFrameTime(nRelativeTime - (nRepeatCount * mnDuration));
+
+ if(DoAlternate() && (nRepeatCount + 1L) % 2L)
+ nFrameTime = mnDuration - nFrameTime;
+
+ return mfStart + ((mfStop - mfStart) *
+ (double(nFrameTime) / mnDuration));
+ }
+ else
+ {
+ // endless
+ sal_uInt32 nFrameTime(nRelativeTime % mnDuration);
+
+ if(DoAlternate())
+ {
+ const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
+
+ if((nRepeatCount + 1L) % 2L)
+ nFrameTime = mnDuration - nFrameTime;
+ }
+
+ return mfStart + ((mfStop - mfStart) * (double(nFrameTime) / mnDuration));
+ }
+}
+
+class ActivityImpl : public Activity,
+ public boost::enable_shared_from_this<ActivityImpl>,
+ private boost::noncopyable
+{
+public:
+ virtual ~ActivityImpl();
+
+ ActivityImpl(
+ SlideShowContext const& rContext,
+ boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
+ boost::shared_ptr<DrawShape> const& pDrawShape );
+
+ bool enableAnimations();
+
+ // Disposable:
+ virtual void dispose();
+ // Activity:
+ virtual double calcTimeLag() const;
+ virtual bool perform();
+ virtual bool isActive() const;
+ virtual void dequeued();
+ virtual void end();
+
+private:
+ void updateShapeAttributes( double fTime,
+ basegfx::B2DRectangle const& parentBounds );
+
+ // Access to VisibleWhenSTarted flags
+ sal_Bool IsVisibleWhenStarted() const { return mbVisibleWhenStarted; }
+ sal_Bool IsVisibleWhenStopped() const { return mbVisibleWhenStopped; }
+
+ // scroll horizontal? if sal_False, scroll is vertical.
+ bool ScrollHorizontal() const {
+ return (drawing::TextAnimationDirection_LEFT == meDirection ||
+ drawing::TextAnimationDirection_RIGHT == meDirection);
+ }
+
+ // Access to StepWidth in logical units
+ sal_uInt32 GetStepWidthLogic() const;
+
+ // is the animation direction opposite?
+ bool DoScrollForward() const {
+ return (drawing::TextAnimationDirection_RIGHT == meDirection ||
+ drawing::TextAnimationDirection_DOWN == meDirection);
+ }
+
+ // do alternate text directions?
+ bool DoAlternate() const { return mbAlternate; }
+
+ // do scroll in?
+ bool DoScrollIn() const { return mbScrollIn; }
+
+ // Scroll helper methods
+ void ImpForceScrollTextAnimNodes();
+ ScrollTextAnimNode* ImpGetScrollTextAnimNode(
+ sal_uInt32 nTime, sal_uInt32& rRelativeTime );
+ sal_uInt32 ImpRegisterAgainScrollTextMixerState(
+ sal_uInt32 nTime);
+
+ // calculate the MixerState value for given time
+ double GetMixerState(sal_uInt32 nTime);
+
+ ////////////////////////////////////////////////////////////////////
+
+ SlideShowContext maContext;
+ boost::shared_ptr<WakeupEvent> mpWakeupEvent;
+ boost::weak_ptr<DrawShape> mpParentDrawShape;
+ DrawShapeSharedPtr mpDrawShape;
+ ShapeAttributeLayerHolder maShapeAttrLayer;
+ GDIMetaFileSharedPtr mpMetaFile;
+ IntrinsicAnimationEventHandlerSharedPtr mpListener;
+ canvas::tools::ElapsedTime maTimer;
+ double mfRotationAngle;
+ bool mbIsShapeAnimated;
+ bool mbIsDisposed;
+ bool mbIsActive;
+ drawing::TextAnimationKind meAnimKind;
+
+ // The blink frequency in ms
+ sal_uInt32 mnFrequency;
+
+ // The repeat count, init to 0L which means endless
+ sal_uInt32 mnRepeat;
+
+ // Flag to decide if text will be shown when animation has ended
+ bool mbVisibleWhenStopped;
+ bool mbVisibleWhenStarted;
+
+ // Flag decides if TextScroll alternates. Default is sal_False.
+ bool mbAlternate;
+
+ // Flag to remember if this is a simple scrollin text
+ bool mbScrollIn;
+
+ // start time for this animation
+ sal_uInt32 mnStartTime;
+
+ // The AnimationDirection
+ drawing::TextAnimationDirection meDirection;
+
+ // Get width per Step. Negative means pixel, positive logical units
+ sal_Int32 mnStepWidth;
+
+ // The single anim steps
+ std::vector< ScrollTextAnimNode > maVector;
+
+ // the scroll rectangle
+ Rectangle maScrollRectangleLogic;
+
+ // the paint rectangle
+ Rectangle maPaintRectangleLogic;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
+ private boost::noncopyable
+{
+public:
+ explicit IntrinsicAnimationListener( ActivityImpl& rActivity ) :
+ mrActivity( rActivity )
+ {}
+
+private:
+
+ virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
+ virtual bool disableAnimations() { mrActivity.end(); return true; }
+
+ ActivityImpl& mrActivity;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+double ActivityImpl::GetMixerState( sal_uInt32 nTime )
+{
+ if( meAnimKind == drawing::TextAnimationKind_BLINK )
+ {
+ // from AInfoBlinkText:
+ double fRetval(0.0);
+ sal_Bool bDone(sal_False);
+ const sal_uInt32 nLoopTime(2 * mnFrequency);
+
+ if(mnRepeat)
+ {
+ const sal_uInt32 nEndTime(mnRepeat * nLoopTime);
+
+ if(nTime >= nEndTime)
+ {
+ if(mbVisibleWhenStopped)
+ fRetval = 0.0;
+ else
+ fRetval = 1.0;
+
+ bDone = sal_True;
+ }
+ }
+
+ if(!bDone)
+ {
+ sal_uInt32 nTimeInLoop(nTime % nLoopTime);
+ fRetval = double(nTimeInLoop) / nLoopTime;
+ }
+
+ return fRetval;
+ }
+ else
+ {
+ // from AInfoScrollText:
+ double fRetval(0.0);
+ ImpForceScrollTextAnimNodes();
+
+ if(!maVector.empty())
+ {
+ sal_uInt32 nRelativeTime;
+ ScrollTextAnimNode* pNode =
+ ImpGetScrollTextAnimNode(nTime, nRelativeTime);
+
+ if(pNode)
+ {
+ // use node
+ fRetval = pNode->GetStateAtRelativeTime(nRelativeTime);
+ }
+ else
+ {
+ // end of animation, take last entry's end
+ fRetval = maVector[maVector.size() - 1L].GetStop();
+ }
+ }
+
+ return fRetval;
+ }
+}
+
+// Access to StepWidth in logical units
+sal_uInt32 ActivityImpl::GetStepWidthLogic() const
+{
+ // #i69847# Assuming higher DPI
+ sal_uInt32 const PIXEL_TO_LOGIC = 30;
+
+ sal_uInt32 nRetval(0L);
+
+ if(mnStepWidth < 0L)
+ {
+ // is in pixels, convert to logical units
+ nRetval = (-mnStepWidth * PIXEL_TO_LOGIC);
+ }
+ else if(mnStepWidth > 0L)
+ {
+ // is in logical units
+ nRetval = mnStepWidth;
+ }
+
+ if(0L == nRetval)
+ {
+ // step 1 pixel, canned value
+
+ // #128389# with very high DPIs like in PDF export, this can
+ // still get zero. for that cases, set a default, too (taken
+ // from ainfoscrolltext.cxx)
+ nRetval = 100L;
+ }
+
+ return nRetval;
+}
+
+void ActivityImpl::ImpForceScrollTextAnimNodes()
+{
+ if(maVector.empty())
+ {
+ // prepare values
+ sal_uInt32 nLoopTime;
+ double fZeroLogic, fOneLogic, fInitLogic, fDistanceLogic;
+ double fZeroLogicAlternate = 0.0, fOneLogicAlternate = 0.0;
+ double fZeroRelative, fOneRelative, fInitRelative,fDistanceRelative;
+
+ if(ScrollHorizontal())
+ {
+ if(DoAlternate())
+ {
+ if(maPaintRectangleLogic.GetWidth() >
+ maScrollRectangleLogic.GetWidth())
+ {
+ fZeroLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
+ fOneLogicAlternate = maScrollRectangleLogic.Left();
+ }
+ else
+ {
+ fZeroLogicAlternate = maScrollRectangleLogic.Left();
+ fOneLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
+ }
+ }
+
+ fZeroLogic = maScrollRectangleLogic.Left() - maPaintRectangleLogic.GetWidth();
+ fOneLogic = maScrollRectangleLogic.Right();
+ fInitLogic = maPaintRectangleLogic.Left();
+ }
+ else
+ {
+ if(DoAlternate())
+ {
+ if(maPaintRectangleLogic.GetHeight() > maScrollRectangleLogic.GetHeight())
+ {
+ fZeroLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
+ fOneLogicAlternate = maScrollRectangleLogic.Top();
+ }
+ else
+ {
+ fZeroLogicAlternate = maScrollRectangleLogic.Top();
+ fOneLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
+ }
+ }
+
+ fZeroLogic = maScrollRectangleLogic.Top() - maPaintRectangleLogic.GetHeight();
+ fOneLogic = maScrollRectangleLogic.Bottom();
+ fInitLogic = maPaintRectangleLogic.Top();
+ }
+
+ fDistanceLogic = fOneLogic - fZeroLogic;
+ fInitRelative = (fInitLogic - fZeroLogic) / fDistanceLogic;
+
+ if(DoAlternate())
+ {
+ fZeroRelative =
+ (fZeroLogicAlternate - fZeroLogic) / fDistanceLogic;
+ fOneRelative =
+ (fOneLogicAlternate - fZeroLogic) / fDistanceLogic;
+ fDistanceRelative = fOneRelative - fZeroRelative;
+ }
+ else
+ {
+ fZeroRelative = 0.0;
+ fOneRelative = 1.0;
+ fDistanceRelative = 1.0;
+ }
+
+ if(mnStartTime)
+ {
+ // Start time loop
+ ScrollTextAnimNode aStartNode(
+ mnStartTime, 1L, 0.0, 0.0, mnStartTime, false);
+ maVector.push_back(aStartNode);
+ }
+
+ if(IsVisibleWhenStarted())
+ {
+ double fRelativeStartValue, fRelativeEndValue,fRelativeDistance;
+
+ if(DoScrollForward())
+ {
+ fRelativeStartValue = fInitRelative;
+ fRelativeEndValue = fOneRelative;
+ fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
+ }
+ else
+ {
+ fRelativeStartValue = fInitRelative;
+ fRelativeEndValue = fZeroRelative;
+ fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
+ }
+
+ const double fNumberSteps =
+ (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
+ nLoopTime = FRound(fNumberSteps * mnFrequency);
+
+ // init loop
+ ScrollTextAnimNode aInitNode(
+ nLoopTime, 1L,
+ fRelativeStartValue, fRelativeEndValue,
+ mnFrequency, false);
+ maVector.push_back(aInitNode);
+ }
+
+ // prepare main loop values
+ {
+ double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
+
+ if(DoScrollForward())
+ {
+ fRelativeStartValue = fZeroRelative;
+ fRelativeEndValue = fOneRelative;
+ fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
+ }
+ else
+ {
+ fRelativeStartValue = fOneRelative;
+ fRelativeEndValue = fZeroRelative;
+ fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
+ }
+
+ const double fNumberSteps =
+ (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
+ nLoopTime = FRound(fNumberSteps * mnFrequency);
+
+ if(0L == mnRepeat)
+ {
+ if(!DoScrollIn())
+ {
+ // endless main loop
+ ScrollTextAnimNode aMainNode(
+ nLoopTime, 0L,
+ fRelativeStartValue, fRelativeEndValue,
+ mnFrequency, DoAlternate());
+ maVector.push_back(aMainNode);
+ }
+ }
+ else
+ {
+ sal_uInt32 nNumRepeat(mnRepeat);
+
+ if(DoAlternate() && (nNumRepeat + 1L) % 2L)
+ nNumRepeat += 1L;
+
+ // ending main loop
+ ScrollTextAnimNode aMainNode(
+ nLoopTime, nNumRepeat,
+ fRelativeStartValue, fRelativeEndValue,
+ mnFrequency, DoAlternate());
+ maVector.push_back(aMainNode);
+ }
+ }
+
+ if(IsVisibleWhenStopped())
+ {
+ double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
+
+ if(DoScrollForward())
+ {
+ fRelativeStartValue = fZeroRelative;
+ fRelativeEndValue = fInitRelative;
+ fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
+ }
+ else
+ {
+ fRelativeStartValue = fOneRelative;
+ fRelativeEndValue = fInitRelative;
+ fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
+ }
+
+ const double fNumberSteps =
+ (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
+ nLoopTime = FRound(fNumberSteps * mnFrequency);
+
+ // exit loop
+ ScrollTextAnimNode aExitNode(
+ nLoopTime, 1L,
+ fRelativeStartValue, fRelativeEndValue, mnFrequency, false);
+ maVector.push_back(aExitNode);
+ }
+ }
+}
+
+ScrollTextAnimNode* ActivityImpl::ImpGetScrollTextAnimNode(
+ sal_uInt32 nTime, sal_uInt32& rRelativeTime )
+{
+ ScrollTextAnimNode* pRetval = 0L;
+ ImpForceScrollTextAnimNodes();
+
+ if(!maVector.empty())
+ {
+ rRelativeTime = nTime;
+
+ for(sal_uInt32 a(0L); !pRetval && a < maVector.size(); a++)
+ {
+ ScrollTextAnimNode & rNode = maVector[a];
+ if(!rNode.GetRepeat())
+ {
+ // endless loop, use it
+ pRetval = &rNode;
+ }
+ else if(rNode.GetFullTime() > rRelativeTime)
+ {
+ // ending node
+ pRetval = &rNode;
+ }
+ else
+ {
+ // look at next
+ rRelativeTime -= rNode.GetFullTime();
+ }
+ }
+ }
+
+ return pRetval;
+}
+
+sal_uInt32 ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime)
+{
+ sal_uInt32 nRetval(0L);
+ ImpForceScrollTextAnimNodes();
+
+ if(maVector.size())
+ {
+ sal_uInt32 nRelativeTime;
+ ScrollTextAnimNode* pNode = ImpGetScrollTextAnimNode(nTime, nRelativeTime);
+
+ if(pNode)
+ {
+ // take register time
+ nRetval = pNode->GetFrequency();
+ }
+ }
+ else
+ {
+ // #i38135# not initialized, return default
+ nRetval = mnFrequency;
+ }
+
+ return nRetval;
+}
+
+void ActivityImpl::updateShapeAttributes(
+ double fTime, basegfx::B2DRectangle const& parentBounds )
+{
+ OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
+ if( meAnimKind == drawing::TextAnimationKind_NONE )
+ return;
+
+ double const fMixerState = GetMixerState(
+ static_cast<sal_uInt32>(fTime * 1000.0) );
+
+ if( meAnimKind == drawing::TextAnimationKind_BLINK )
+ {
+ // show/hide text:
+ maShapeAttrLayer.get()->setVisibility( fMixerState < 0.5 );
+ }
+ else if(mpMetaFile) // scroll mode:
+ {
+ //
+ // keep care: the below code is highly sensible to changes...
+ //
+
+ // rectangle of the pure text:
+ double const fPaintWidth = maPaintRectangleLogic.GetWidth();
+ double const fPaintHeight = maPaintRectangleLogic.GetHeight();
+ // rectangle where the scrolling takes place (-> clipping):
+ double const fScrollWidth = maScrollRectangleLogic.GetWidth();
+ double const fScrollHeight = maScrollRectangleLogic.GetHeight();
+
+ basegfx::B2DPoint pos, clipPos;
+
+ if(ScrollHorizontal())
+ {
+ double const fOneEquiv( fScrollWidth );
+ double const fZeroEquiv( -fPaintWidth );
+
+ pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
+
+ clipPos.setX( -pos.getX() );
+ clipPos.setY( -pos.getY() );
+
+ // #i69844# Compensation for text-wider-than-shape case
+ if( fPaintWidth > fScrollWidth )
+ pos.setX( pos.getX() + (fPaintWidth-fScrollWidth) / 2.0 );
+ }
+ else
+ {
+ // scroll vertical:
+ double const fOneEquiv( fScrollHeight );
+ double const fZeroEquiv( -fPaintHeight );
+
+ pos.setY( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
+
+ clipPos.setX( -pos.getX() );
+ clipPos.setY( -pos.getY() );
+
+ // #i69844# Compensation for text-higher-than-shape case
+ if( fPaintHeight > fScrollHeight )
+ pos.setY( pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 );
+ }
+
+ basegfx::B2DPolygon clipPoly(
+ basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRectangle( clipPos.getX(),
+ clipPos.getY(),
+ clipPos.getX() + fScrollWidth,
+ clipPos.getY() + fScrollHeight ) ) );
+
+ if( !::basegfx::fTools::equalZero( mfRotationAngle ))
+ {
+ maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle );
+ double const fRotate = (mfRotationAngle * M_PI / 180.0);
+ basegfx::B2DHomMatrix aTransform;
+ // position:
+ aTransform.rotate( fRotate );
+ pos *= aTransform;
+ }
+
+ pos += parentBounds.getCenter();
+ maShapeAttrLayer.get()->setPosition( pos );
+ maShapeAttrLayer.get()->setClip( basegfx::B2DPolyPolygon(clipPoly) );
+ }
+}
+
+bool ActivityImpl::perform()
+{
+ if( !isActive() )
+ return false;
+
+ ENSURE_OR_RETURN_FALSE(
+ mpDrawShape,
+ "ActivityImpl::perform(): still active, but NULL draw shape" );
+
+ DrawShapeSharedPtr const pParentDrawShape( mpParentDrawShape );
+ if( !pParentDrawShape )
+ return false; // parent has vanished
+
+ if( pParentDrawShape->isVisible() )
+ {
+ if( !mbIsShapeAnimated )
+ {
+ mpDrawShape->setVisibility(true); // shape may be initially hidden
+ maContext.mpSubsettableShapeManager->enterAnimationMode( mpDrawShape );
+ maTimer.reset();
+ mbIsShapeAnimated = true;
+ }
+ // update attributes related to current time:
+ basegfx::B2DRectangle const parentBounds(
+ pParentDrawShape->getBounds() );
+
+ const double nCurrTime( maTimer.getElapsedTime() );
+ updateShapeAttributes( nCurrTime, parentBounds );
+
+ const sal_uInt32 nFrequency(
+ ImpRegisterAgainScrollTextMixerState(
+ static_cast<sal_uInt32>(nCurrTime * 1000.0)) );
+
+ if(nFrequency)
+ {
+ mpWakeupEvent->start();
+ mpWakeupEvent->setNextTimeout(
+ std::max(0.1,nFrequency/1000.0) );
+ maContext.mrEventQueue.addEvent( mpWakeupEvent );
+
+ if( mpDrawShape->isContentChanged() )
+ maContext.mpSubsettableShapeManager->notifyShapeUpdate( mpDrawShape );
+ }
+ // else: finished, not need to wake up again.
+ }
+ else
+ {
+ // busy-wait, until parent shape gets visible
+ mpWakeupEvent->start();
+ mpWakeupEvent->setNextTimeout( 2.0 );
+ }
+
+ // don't reinsert, WakeupEvent will perform that after the given timeout:
+ return false;
+}
+
+ActivityImpl::ActivityImpl(
+ SlideShowContext const& rContext,
+ boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
+ boost::shared_ptr<DrawShape> const& pParentDrawShape )
+ : maContext(rContext),
+ mpWakeupEvent(pWakeupEvent),
+ mpParentDrawShape(pParentDrawShape),
+ mpListener( new IntrinsicAnimationListener(*this) ),
+ maTimer(rContext.mrEventQueue.getTimer()),
+ mbIsShapeAnimated(false),
+ mbIsDisposed(false),
+ mbIsActive(true),
+ meAnimKind(drawing::TextAnimationKind_NONE),
+ mnStartTime(0L)
+{
+ // get doctreenode:
+ sal_Int32 const nNodes = pParentDrawShape->getNumberOfTreeNodes(
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH );
+
+ DocTreeNode scrollTextNode(
+ pParentDrawShape->getTreeNode(
+ 0, DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ));
+ // xxx todo: remove this hack
+ if( nNodes > 1 )
+ scrollTextNode.setEndIndex(
+ pParentDrawShape->getTreeNode(
+ nNodes - 1,
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ).getEndIndex());
+
+ // TODO(Q3): Doing this manually, instead of using
+ // ShapeSubset. This is because of lifetime issues (ShapeSubset
+ // generates circular references to parent shape)
+ mpDrawShape = boost::dynamic_pointer_cast<DrawShape>(
+ maContext.mpSubsettableShapeManager->getSubsetShape(
+ pParentDrawShape,
+ scrollTextNode ));
+
+ mpMetaFile = mpDrawShape->forceScrollTextMetaFile();
+
+ // make scroll text invisible for slide transition bitmaps
+ mpDrawShape->setVisibility(false);
+
+ basegfx::B2DRectangle aScrollRect, aPaintRect;
+ ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
+ aPaintRect,
+ mpMetaFile ),
+ "ActivityImpl::ActivityImpl(): Could not extract "
+ "scroll anim rectangles from mtf" );
+
+ maScrollRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
+ aScrollRect );
+ maPaintRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
+ aPaintRect );
+
+ maShapeAttrLayer.createAttributeLayer(mpDrawShape);
+
+ uno::Reference<drawing::XShape> const xShape( mpDrawShape->getXShape() );
+ uno::Reference<beans::XPropertySet> const xProps( xShape, uno::UNO_QUERY_THROW );
+
+ getPropertyValue( meAnimKind, xProps, OUSTR("TextAnimationKind") );
+ OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
+ mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE);
+ mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE);
+
+ // adopted from in AInfoBlinkText::ImplInit():
+ sal_Int16 nRepeat(0);
+ getPropertyValue( nRepeat, xProps, OUSTR("TextAnimationCount") );
+ mnRepeat = nRepeat;
+
+ if(mbAlternate)
+ {
+ // force visible when started for scroll-forth-and-back, because
+ // slide has been coming in with visible text in the middle:
+ mbVisibleWhenStarted = true;
+ }
+ else
+ {
+ getPropertyValue( mbVisibleWhenStarted, xProps,
+ OUSTR("TextAnimationStartInside") );
+ }
+
+ // set visible when stopped
+ getPropertyValue( mbVisibleWhenStopped, xProps,
+ OUSTR("TextAnimatiogonStopInside") );
+ // rotation:
+ getPropertyValue( mfRotationAngle, xProps,
+ OUSTR("RotateAngle") );
+ mfRotationAngle /= -100.0; // (switching direction)
+
+ // set frequency
+ sal_Int16 nDelay(0);
+ getPropertyValue( nDelay, xProps, OUSTR("TextAnimationDelay") );
+ // set delay if not automatic
+ mnFrequency = (nDelay ? nDelay :
+ // default:
+ meAnimKind == drawing::TextAnimationKind_BLINK
+ ? 250L : 50L );
+
+ // adopted from in AInfoScrollText::ImplInit():
+
+ // If it is a simple m_bScrollIn, reset some parameters
+ if( DoScrollIn() )
+ {
+ // most parameters are set correctly from the dialog logic, but
+ // eg VisisbleWhenStopped is grayed out and needs to be corrected here.
+ mbVisibleWhenStopped = true;
+ mbVisibleWhenStarted = false;
+ mnRepeat = 0L;
+ }
+
+ // Get animation direction
+ getPropertyValue( meDirection, xProps, OUSTR("TextAnimationDirection") );
+
+ // Get step width. Negative means pixel, positive logical units
+ getPropertyValue( mnStepWidth, xProps, OUSTR("TextAnimationAmount") );
+
+ maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
+ mpListener );
+}
+
+bool ActivityImpl::enableAnimations()
+{
+ mbIsActive = true;
+ return maContext.mrActivitiesQueue.addActivity(
+ shared_from_this() );
+}
+
+ActivityImpl::~ActivityImpl()
+{
+}
+
+void ActivityImpl::dispose()
+{
+ if( !mbIsDisposed )
+ {
+ end();
+
+ // only remove subset here, since end() is called on slide end
+ // (and we must not spoil the slide preview bitmap with scroll
+ // text)
+ maShapeAttrLayer.reset();
+ if( mpDrawShape )
+ {
+ // TODO(Q3): Doing this manually, instead of using
+ // ShapeSubset. This is because of lifetime issues
+ // (ShapeSubset generates circular references to parent
+ // shape)
+ DrawShapeSharedPtr pParent( mpParentDrawShape.lock() );
+ if( pParent )
+ maContext.mpSubsettableShapeManager->revokeSubset(
+ pParent,
+ mpDrawShape );
+ }
+
+ mpMetaFile.reset();
+ mpDrawShape.reset();
+ mpParentDrawShape.reset();
+ mpWakeupEvent.reset();
+ maContext.dispose();
+ mbIsDisposed = true;
+
+ maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
+ mpListener );
+ }
+}
+
+double ActivityImpl::calcTimeLag() const
+{
+ return 0.0;
+}
+
+bool ActivityImpl::isActive() const
+{
+ return mbIsActive;
+}
+
+void ActivityImpl::dequeued()
+{
+ // not used here
+}
+
+void ActivityImpl::end()
+{
+ // not used here
+ mbIsActive = false;
+
+ if( mbIsShapeAnimated )
+ {
+ maContext.mpSubsettableShapeManager->leaveAnimationMode( mpDrawShape );
+ mbIsShapeAnimated = false;
+ }
+}
+
+} // anon namespace
+
+namespace slideshow {
+namespace internal {
+
+boost::shared_ptr<Activity> createDrawingLayerAnimActivity(
+ SlideShowContext const& rContext,
+ boost::shared_ptr<DrawShape> const& pDrawShape )
+{
+ boost::shared_ptr<Activity> pActivity;
+
+ try
+ {
+ boost::shared_ptr<WakeupEvent> const pWakeupEvent(
+ new WakeupEvent( rContext.mrEventQueue.getTimer(),
+ rContext.mrActivitiesQueue ) );
+ pActivity.reset( new ActivityImpl( rContext, pWakeupEvent, pDrawShape ) );
+ pWakeupEvent->setActivity( pActivity );
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ // translate any error into empty factory product.
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+ return pActivity;
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawinglayeranimation.hxx b/slideshow/source/engine/shapes/drawinglayeranimation.hxx
new file mode 100644
index 000000000000..b1d2bd1c60a3
--- /dev/null
+++ b/slideshow/source/engine/shapes/drawinglayeranimation.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_DRAWINGLAYERANIMATION_HXX
+#define INCLUDED_DRAWINGLAYERANIMATION_HXX
+
+#include <sal/config.h>
+#include <boost/shared_ptr.hpp>
+
+namespace slideshow {
+namespace internal {
+
+class Activity;
+struct SlideShowContext;
+class DrawShape;
+
+boost::shared_ptr<Activity> createDrawingLayerAnimActivity(
+ SlideShowContext const& rContext,
+ boost::shared_ptr<DrawShape> const& pDrawShape );
+
+} // namespace internal
+} // namespace presentation
+
+#endif // ! defined INCLUDED_DRAWINGLAYERANIMATION_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawshape.cxx b/slideshow/source/engine/shapes/drawshape.cxx
new file mode 100644
index 000000000000..605532f3673e
--- /dev/null
+++ b/slideshow/source/engine/shapes/drawshape.cxx
@@ -0,0 +1,1481 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <rtl/logfile.hxx>
+#include <osl/diagnose.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <vcl/metaact.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/wrkwin.hxx>
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/range/rangeexpander.hxx>
+
+#include <rtl/math.hxx>
+
+#include <com/sun/star/drawing/TextAnimationKind.hpp>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <tools/stream.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
+
+#include <comphelper/scopeguard.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <cmath> // for trigonometry and fabs
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+#include "drawshapesubsetting.hxx"
+#include "drawshape.hxx"
+#include "eventqueue.hxx"
+#include "wakeupevent.hxx"
+#include "subsettableshapemanager.hxx"
+#include "intrinsicanimationactivity.hxx"
+#include "slideshowexceptions.hxx"
+#include "tools.hxx"
+#include "gdimtftools.hxx"
+#include "drawinglayeranimation.hxx"
+
+#include <boost/bind.hpp>
+#include <math.h>
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
+ //metafiles are resolution dependent when bitmaps are contained with is the case for 3D scenes for example
+ //in addition a chart has resolution dependent content as it might skip points that are not visible for a given resolution (this is done for performance reasons)
+ bool local_getMetafileForChart( const uno::Reference< lang::XComponent >& xSource,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ GDIMetaFile& rMtf )
+ {
+ //get the chart model
+ uno::Reference< beans::XPropertySet > xPropSet( xSource, uno::UNO_QUERY );
+ uno::Reference< frame::XModel > xChartModel;
+ getPropertyValue( xChartModel, xPropSet, OUSTR("Model"));
+ uno::Reference< lang::XMultiServiceFactory > xFact( xChartModel, uno::UNO_QUERY );
+ OSL_ENSURE( xFact.is(), "Chart cannot be painted pretty!\n" );
+ if(!xFact.is())
+ return false;
+
+ //get the chart view
+ uno::Reference< datatransfer::XTransferable > xChartViewTransferable(
+ xFact->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.ChartView" ) ) ), uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xChartViewProp( xChartViewTransferable, uno::UNO_QUERY );
+ OSL_ENSURE( xChartViewProp.is(), "Chart cannot be painted pretty!\n" );
+ if( !xChartViewProp.is() )
+ return false;
+
+ //estimate zoom and resolution (this is only a workaround, correct would be to know and use the exact zoom and resoltion during slideshow display)
+ sal_Int32 nScaleXNumerator = 100;//zoom factor -> exact values are important for the quality of the created bitmap especially for 3D charts
+ sal_Int32 nScaleYNumerator = 100;
+ sal_Int32 nScaleXDenominator = 100;
+ sal_Int32 nScaleYDenominator = 100;
+ awt::Size aPixelPerChart( 1000, 1000 );//when data points happen to be on the same pixel as their predecessor no shape is created to safe performance
+
+ Window* pActiveTopWindow( Application::GetActiveTopWindow() );
+ WorkWindow* pWorkWindow( dynamic_cast<WorkWindow*>(pActiveTopWindow));
+ if( pWorkWindow && pWorkWindow->IsPresentationMode() )
+ {
+ Size aPixScreenSize( pActiveTopWindow->GetOutputSizePixel() );
+ aPixelPerChart = awt::Size( aPixScreenSize.getWidth(), aPixScreenSize.getHeight() );//this is still to much (but costs only seldom performance), correct would be pixel per chart object
+
+ uno::Reference< beans::XPropertySet > xPageProp( xContainingPage, uno::UNO_QUERY );
+ sal_Int32 nLogicPageWidth=1;
+ sal_Int32 nLogicPageHeight=1;
+ if( getPropertyValue( nLogicPageWidth, xPageProp, OUSTR("Width")) &&
+ getPropertyValue( nLogicPageHeight, xPageProp, OUSTR("Height")) )
+ {
+ Size aLogicScreenSize( pActiveTopWindow->PixelToLogic( aPixScreenSize, MAP_100TH_MM ) );
+ nScaleXNumerator = aLogicScreenSize.getWidth();
+ nScaleYNumerator = aLogicScreenSize.getHeight();
+ nScaleXDenominator = nLogicPageWidth;
+ nScaleYDenominator = nLogicPageHeight;
+ }
+ }
+ else
+ {
+ long nMaxPixWidth = 0;
+ long nMaxPixHeight = 0;
+ unsigned int nScreenCount( Application::GetScreenCount() );
+ for( unsigned int nScreen=0; nScreen<nScreenCount; nScreen++ )
+ {
+ Rectangle aCurScreenRect( Application::GetScreenPosSizePixel( nScreen ) );
+ if( aCurScreenRect.GetWidth() > nMaxPixWidth )
+ nMaxPixWidth = aCurScreenRect.GetWidth();
+ if( aCurScreenRect.GetHeight() > nMaxPixHeight )
+ nMaxPixHeight = aCurScreenRect.GetHeight();
+ }
+ if(nMaxPixWidth>1 && nMaxPixHeight>1)
+ aPixelPerChart = awt::Size( nMaxPixWidth, nMaxPixHeight );//this is still to much (but costs only seldom performance), correct would be pixel per chart object
+ }
+
+ try
+ {
+ uno::Sequence< beans::PropertyValue > aZoomFactors(4);
+ aZoomFactors[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleXNumerator") );
+ aZoomFactors[0].Value = uno::makeAny( nScaleXNumerator );
+ aZoomFactors[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleXDenominator") );
+ aZoomFactors[1].Value = uno::makeAny( nScaleXDenominator );
+ aZoomFactors[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleYNumerator") );
+ aZoomFactors[2].Value = uno::makeAny( nScaleYNumerator );
+ aZoomFactors[3].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleYDenominator") );
+ aZoomFactors[3].Value = uno::makeAny( nScaleYDenominator );
+
+ xChartViewProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ZoomFactors") ), uno::makeAny( aZoomFactors ));
+ xChartViewProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Resolution") ), uno::makeAny( aPixelPerChart ));
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+ //get a metafile from the prepared chart view
+ datatransfer::DataFlavor aDataFlavor(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"") ),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GDIMetaFile" ) ),
+ ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) );
+ uno::Any aData( xChartViewTransferable->getTransferData( aDataFlavor ) );
+ uno::Sequence< sal_Int8 > aSeq;
+ if( aData >>= aSeq )
+ {
+ ::std::auto_ptr< SvMemoryStream > pSrcStm( new SvMemoryStream( (char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_WRITE | STREAM_TRUNC ) );
+ *(pSrcStm.get() ) >> rMtf;
+ return true;
+ }
+ return false;
+ }
+
+ //same as getMetafile with an exception for charts
+ //for charts a metafile with a higher resolution is created, because charts have resolution dependent content
+ bool local_getMetaFile_WithSpecialChartHandling( const uno::Reference< lang::XComponent >& xSource,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ GDIMetaFile& rMtf,
+ int mtfLoadFlags,
+ const uno::Reference< uno::XComponentContext >& rxContext )
+ {
+ uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY );
+ rtl::OUString sCLSID;
+ getPropertyValue( sCLSID, xProp, OUSTR("CLSID"));
+ if( sCLSID.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("12DCAE26-281F-416F-a234-c3086127382e")) && local_getMetafileForChart( xSource, xContainingPage, rMtf ) )
+ return true;
+ return getMetaFile( xSource, xContainingPage, rMtf, mtfLoadFlags, rxContext );
+ }
+
+
+ //////////////////////////////////////////////////////////////////////
+ //
+ // Private methods
+ //
+ //////////////////////////////////////////////////////////////////////
+
+ GDIMetaFileSharedPtr DrawShape::forceScrollTextMetaFile()
+ {
+ if ((mnCurrMtfLoadFlags & MTF_LOAD_SCROLL_TEXT_MTF) != MTF_LOAD_SCROLL_TEXT_MTF)
+ {
+ // reload with added flags:
+ mpCurrMtf.reset( new GDIMetaFile );
+ mnCurrMtfLoadFlags |= MTF_LOAD_SCROLL_TEXT_MTF;
+ local_getMetaFile_WithSpecialChartHandling(
+ uno::Reference<lang::XComponent>(mxShape, uno::UNO_QUERY),
+ mxPage, *mpCurrMtf, mnCurrMtfLoadFlags,
+ mxComponentContext );
+
+ // TODO(F1): Currently, the scroll metafile will
+ // never contain any verbose text comments. Thus,
+ // can only display the full mtf content, no
+ // subsets.
+ maSubsetting.reset( mpCurrMtf );
+
+ // adapt maBounds. the requested scroll text metafile
+ // will typically have dimension different from the
+ // actual shape
+ ::basegfx::B2DRectangle aScrollRect, aPaintRect;
+ ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
+ aPaintRect,
+ mpCurrMtf ),
+ "DrawShape::forceScrollTextMetaFile(): Could "
+ "not extract scroll anim rectangles from mtf" );
+
+ // take the larger one of the two rectangles (that
+ // should be the bound rect of the retrieved
+ // metafile)
+ if( aScrollRect.isInside( aPaintRect ) )
+ maBounds = aScrollRect;
+ else
+ maBounds = aPaintRect;
+ }
+ return mpCurrMtf;
+ }
+
+ void DrawShape::updateStateIds() const
+ {
+ // Update the states, we've just redrawn or created a new
+ // attribute layer.
+ if( mpAttributeLayer )
+ {
+ mnAttributeTransformationState = mpAttributeLayer->getTransformationState();
+ mnAttributeClipState = mpAttributeLayer->getClipState();
+ mnAttributeAlphaState = mpAttributeLayer->getAlphaState();
+ mnAttributePositionState = mpAttributeLayer->getPositionState();
+ mnAttributeContentState = mpAttributeLayer->getContentState();
+ mnAttributeVisibilityState = mpAttributeLayer->getVisibilityState();
+ }
+ }
+
+ void DrawShape::ensureVerboseMtfComments() const
+ {
+ // TODO(F1): Text effects don't currently work for drawing
+ // layer animations.
+
+ // only touch mpCurrMtf, if we're not a DrawingLayer
+ // animation.
+ if( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) == 0 &&
+ maAnimationFrames.empty() )
+ {
+ ENSURE_OR_THROW( !maSubsetting.hasSubsetShapes(),
+ "DrawShape::ensureVerboseMtfComments(): reloading the metafile "
+ "with active child subsets will wreak havoc on the view!" );
+ ENSURE_OR_THROW( maSubsetting.getSubsetNode().isEmpty(),
+ "DrawShape::ensureVerboseMtfComments(): reloading the metafile "
+ "for an ALREADY SUBSETTED shape is not possible!" );
+
+ // re-fetch metafile with comments
+ // note that, in case of shapes without text, the new
+ // metafile might still not provide any useful
+ // subsetting information!
+ mpCurrMtf.reset( new GDIMetaFile );
+ mnCurrMtfLoadFlags |= MTF_LOAD_VERBOSE_COMMENTS;
+ local_getMetaFile_WithSpecialChartHandling(
+ uno::Reference<lang::XComponent>(mxShape, uno::UNO_QUERY),
+ mxPage, *mpCurrMtf, mnCurrMtfLoadFlags,
+ mxComponentContext );
+
+ maSubsetting.reset( maSubsetting.getSubsetNode(),
+ mpCurrMtf );
+ }
+ }
+
+ ViewShape::RenderArgs DrawShape::getViewRenderArgs() const
+ {
+ return ViewShape::RenderArgs(
+ maBounds,
+ getUpdateArea(),
+ getBounds(),
+ getActualUnitShapeBounds(),
+ mpAttributeLayer,
+ maSubsetting.getActiveSubsets(),
+ mnPriority);
+ }
+
+ bool DrawShape::implRender( int nUpdateFlags ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShape::implRender()" );
+ RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::presentation::internal::DrawShape: 0x%X", this );
+
+ // will perform the update now, clear update-enforcing
+ // flags
+ mbForceUpdate = false;
+ mbAttributeLayerRevoked = false;
+
+ ENSURE_OR_RETURN_FALSE( !maViewShapes.empty(),
+ "DrawShape::implRender(): render called on DrawShape without views" );
+
+ if( maBounds.isEmpty() )
+ {
+ // zero-sized shapes are effectively invisible,
+ // thus, we save us the rendering...
+ return true;
+ }
+
+ // redraw all view shapes, by calling their update() method
+ if( ::std::count_if( maViewShapes.begin(),
+ maViewShapes.end(),
+ ::boost::bind<bool>(
+ ::boost::mem_fn( &ViewShape::update ), // though _theoretically_,
+ // bind should eat this even
+ // with _1 being a shared_ptr,
+ // it does _not_ for MSVC without
+ // the extra mem_fn. WTF.
+ _1,
+ ::boost::cref( mpCurrMtf ),
+ ::boost::cref(
+ getViewRenderArgs() ),
+ nUpdateFlags,
+ isVisible() ) )
+ != static_cast<ViewShapeVector::difference_type>(maViewShapes.size()) )
+ {
+ // at least one of the ViewShape::update() calls did return
+ // false - update failed on at least one ViewLayer
+ return false;
+ }
+
+ // successfully redrawn - update state IDs to detect next changes
+ updateStateIds();
+
+ return true;
+ }
+
+ int DrawShape::getUpdateFlags() const
+ {
+ // default: update nothing, unless ShapeAttributeStack
+ // tells us below, or if the attribute layer was revoked
+ int nUpdateFlags(ViewShape::NONE);
+
+ // possibly the whole shape content changed
+ if( mbAttributeLayerRevoked )
+ nUpdateFlags = ViewShape::CONTENT;
+
+
+ // determine what has to be updated
+ // --------------------------------
+
+ // do we have an attribute layer?
+ if( mpAttributeLayer )
+ {
+ // Prevent nUpdateFlags to be modified when the shape is not
+ // visible, except when it just was hidden.
+ if (mpAttributeLayer->getVisibility()
+ || mpAttributeLayer->getVisibilityState() != mnAttributeVisibilityState )
+ {
+ if (mpAttributeLayer->getVisibilityState() != mnAttributeVisibilityState )
+ {
+ // Change of the visibility state is mapped to
+ // content change because when the visibility
+ // changes then usually a sprite is shown or hidden
+ // and the background under has to be painted once.
+ nUpdateFlags |= ViewShape::CONTENT;
+ }
+
+ // TODO(P1): This can be done without conditional branching.
+ // See HAKMEM.
+ if( mpAttributeLayer->getPositionState() != mnAttributePositionState )
+ {
+ nUpdateFlags |= ViewShape::POSITION;
+ }
+ if( mpAttributeLayer->getAlphaState() != mnAttributeAlphaState )
+ {
+ nUpdateFlags |= ViewShape::ALPHA;
+ }
+ if( mpAttributeLayer->getClipState() != mnAttributeClipState )
+ {
+ nUpdateFlags |= ViewShape::CLIP;
+ }
+ if( mpAttributeLayer->getTransformationState() != mnAttributeTransformationState )
+ {
+ nUpdateFlags |= ViewShape::TRANSFORMATION;
+ }
+ if( mpAttributeLayer->getContentState() != mnAttributeContentState )
+ {
+ nUpdateFlags |= ViewShape::CONTENT;
+ }
+ }
+ }
+
+ return nUpdateFlags;
+ }
+
+ ::basegfx::B2DRectangle DrawShape::getActualUnitShapeBounds() const
+ {
+ ENSURE_OR_THROW( !maViewShapes.empty(),
+ "DrawShape::getActualUnitShapeBounds(): called on DrawShape without views" );
+
+ const VectorOfDocTreeNodes& rSubsets(
+ maSubsetting.getActiveSubsets() );
+
+ const ::basegfx::B2DRectangle aDefaultBounds( 0.0,0.0,1.0,1.0 );
+
+ // perform the cheapest check first
+ if( rSubsets.empty() )
+ {
+ // if subset contains the whole shape, no need to call
+ // the somewhat expensive bound calculation, since as
+ // long as the subset is empty, this branch will be
+ // taken.
+ return aDefaultBounds;
+ }
+ else
+ {
+ OSL_ENSURE( rSubsets.size() != 1 ||
+ !rSubsets.front().isEmpty(),
+ "DrawShape::getActualUnitShapeBounds() expects a "
+ "_non-empty_ subset vector for a subsetted shape!" );
+
+ // are the cached bounds still valid?
+ if( !maCurrentShapeUnitBounds )
+ {
+ // no, (re)generate them
+ // =====================
+
+ // setup cached values to defaults (might fail to
+ // retrieve true bounds below)
+ maCurrentShapeUnitBounds.reset( aDefaultBounds );
+
+ // TODO(P2): the subset of the master shape (that from
+ // which the subsets are subtracted) changes
+ // relatively often (every time a subset shape is
+ // added or removed). Maybe we should exclude it here,
+ // always assuming full bounds?
+
+ ::cppcanvas::CanvasSharedPtr pDestinationCanvas(
+ maViewShapes.front()->getViewLayer()->getCanvas() );
+
+ // TODO(Q2): Although this _is_ currently
+ // view-agnostic, it might not stay like
+ // that. Maybe this method should again be moved
+ // to the ViewShape
+ ::cppcanvas::RendererSharedPtr pRenderer(
+ maViewShapes.front()->getRenderer(
+ pDestinationCanvas, mpCurrMtf, mpAttributeLayer ) );
+
+ // If we cannot not prefetch, be defensive and assume
+ // full shape size
+ if( pRenderer )
+ {
+ // temporarily, switch total transformation to identity
+ // (need the bounds in the [0,1]x[0,1] unit coordinate
+ // system.
+ ::basegfx::B2DHomMatrix aEmptyTransformation;
+
+ ::basegfx::B2DHomMatrix aOldTransform( pDestinationCanvas->getTransformation() );
+ pDestinationCanvas->setTransformation( aEmptyTransformation );
+ pRenderer->setTransformation( aEmptyTransformation );
+
+ // restore old transformation when leaving the scope
+ const ::comphelper::ScopeGuard aGuard(
+ boost::bind( &::cppcanvas::Canvas::setTransformation,
+ pDestinationCanvas, aOldTransform ) );
+
+
+ // retrieve bounds for subset of whole metafile
+ // --------------------------------------------
+
+ ::basegfx::B2DRange aTotalBounds;
+
+ // cannot use ::boost::bind, ::basegfx::B2DRange::expand()
+ // is overloaded.
+ VectorOfDocTreeNodes::const_iterator aCurr( rSubsets.begin() );
+ const VectorOfDocTreeNodes::const_iterator aEnd( rSubsets.end() );
+ while( aCurr != aEnd )
+ {
+ aTotalBounds.expand( pRenderer->getSubsetArea(
+ aCurr->getStartIndex(),
+ aCurr->getEndIndex() ) );
+ ++aCurr;
+ }
+
+ OSL_ENSURE( aTotalBounds.getMinX() >= -0.1 &&
+ aTotalBounds.getMinY() >= -0.1 &&
+ aTotalBounds.getMaxX() <= 1.1 &&
+ aTotalBounds.getMaxY() <= 1.1,
+ "DrawShape::getActualUnitShapeBounds(): bounds noticeably larger than original shape - clipping!" );
+
+ // really make sure no shape appears larger than its
+ // original bounds (there _are_ some pathologic cases,
+ // especially when imported from PPT, that have
+ // e.g. obscenely large polygon bounds)
+ aTotalBounds.intersect(
+ ::basegfx::B2DRange( 0.0, 0.0,
+ 1.0, 1.0 ));
+
+ maCurrentShapeUnitBounds.reset( aTotalBounds );
+ }
+ }
+
+ return *maCurrentShapeUnitBounds;
+ }
+ }
+
+ DrawShape::DrawShape( const uno::Reference< drawing::XShape >& xShape,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ bool bForeignSource,
+ const SlideShowContext& rContext ) :
+ mxShape( xShape ),
+ mxPage( xContainingPage ),
+ maAnimationFrames(), // empty, we don't have no intrinsic animation
+ mnCurrFrame(0),
+ mpCurrMtf(),
+ mnCurrMtfLoadFlags( bForeignSource
+ ? MTF_LOAD_FOREIGN_SOURCE : MTF_LOAD_NONE ),
+ maCurrentShapeUnitBounds(),
+ mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
+ maBounds( getAPIShapeBounds( xShape ) ),
+ mpAttributeLayer(),
+ mpIntrinsicAnimationActivity(),
+ mnAttributeTransformationState(0),
+ mnAttributeClipState(0),
+ mnAttributeAlphaState(0),
+ mnAttributePositionState(0),
+ mnAttributeContentState(0),
+ mnAttributeVisibilityState(0),
+ maViewShapes(),
+ mxComponentContext( rContext.mxComponentContext ),
+ maHyperlinkIndices(),
+ maHyperlinkRegions(),
+ maSubsetting(),
+ mnIsAnimatedCount(0),
+ mnAnimationLoopCount(0),
+ meCycleMode(CYCLE_LOOP),
+ mbIsVisible( true ),
+ mbForceUpdate( false ),
+ mbAttributeLayerRevoked( false ),
+ mbDrawingLayerAnim( false )
+ {
+ ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" );
+ ENSURE_OR_THROW( mxPage.is(), "DrawShape::DrawShape(): Invalid containing page" );
+
+ // check for drawing layer animations:
+ drawing::TextAnimationKind eKind = drawing::TextAnimationKind_NONE;
+ uno::Reference<beans::XPropertySet> xPropSet( mxShape,
+ uno::UNO_QUERY );
+ if( xPropSet.is() )
+ getPropertyValue( eKind, xPropSet,
+ OUSTR("TextAnimationKind") );
+ mbDrawingLayerAnim = (eKind != drawing::TextAnimationKind_NONE);
+
+ // must NOT be called from within initializer list, uses
+ // state from mnCurrMtfLoadFlags!
+ mpCurrMtf.reset( new GDIMetaFile );
+ local_getMetaFile_WithSpecialChartHandling(
+ uno::Reference<lang::XComponent>(xShape, uno::UNO_QUERY),
+ xContainingPage, *mpCurrMtf, mnCurrMtfLoadFlags,
+ mxComponentContext );
+ ENSURE_OR_THROW( mpCurrMtf,
+ "DrawShape::DrawShape(): Invalid metafile" );
+ maSubsetting.reset( mpCurrMtf );
+
+ prepareHyperlinkIndices();
+ }
+
+ DrawShape::DrawShape( const uno::Reference< drawing::XShape >& xShape,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ const Graphic& rGraphic,
+ const SlideShowContext& rContext ) :
+ mxShape( xShape ),
+ mxPage( xContainingPage ),
+ maAnimationFrames(),
+ mnCurrFrame(0),
+ mpCurrMtf(),
+ mnCurrMtfLoadFlags( MTF_LOAD_NONE ),
+ maCurrentShapeUnitBounds(),
+ mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
+ maBounds( getAPIShapeBounds( xShape ) ),
+ mpAttributeLayer(),
+ mpIntrinsicAnimationActivity(),
+ mnAttributeTransformationState(0),
+ mnAttributeClipState(0),
+ mnAttributeAlphaState(0),
+ mnAttributePositionState(0),
+ mnAttributeContentState(0),
+ mnAttributeVisibilityState(0),
+ maViewShapes(),
+ mxComponentContext( rContext.mxComponentContext ),
+ maHyperlinkIndices(),
+ maHyperlinkRegions(),
+ maSubsetting(),
+ mnIsAnimatedCount(0),
+ mnAnimationLoopCount(0),
+ meCycleMode(CYCLE_LOOP),
+ mbIsVisible( true ),
+ mbForceUpdate( false ),
+ mbAttributeLayerRevoked( false ),
+ mbDrawingLayerAnim( false )
+ {
+ ENSURE_OR_THROW( rGraphic.IsAnimated(),
+ "DrawShape::DrawShape(): Graphic is no animation" );
+
+ getAnimationFromGraphic( maAnimationFrames,
+ mnAnimationLoopCount,
+ meCycleMode,
+ rGraphic );
+
+ ENSURE_OR_THROW( !maAnimationFrames.empty() &&
+ maAnimationFrames.front().mpMtf,
+ "DrawShape::DrawShape(): " );
+ mpCurrMtf = maAnimationFrames.front().mpMtf;
+
+ ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" );
+ ENSURE_OR_THROW( mxPage.is(), "DrawShape::DrawShape(): Invalid containing page" );
+ ENSURE_OR_THROW( mpCurrMtf, "DrawShape::DrawShape(): Invalid metafile" );
+ }
+
+ DrawShape::DrawShape( const DrawShape& rSrc,
+ const DocTreeNode& rTreeNode,
+ double nPrio ) :
+ mxShape( rSrc.mxShape ),
+ mxPage( rSrc.mxPage ),
+ maAnimationFrames(), // don't copy animations for subsets,
+ // only the current frame!
+ mnCurrFrame(0),
+ mpCurrMtf( rSrc.mpCurrMtf ),
+ mnCurrMtfLoadFlags( rSrc.mnCurrMtfLoadFlags ),
+ maCurrentShapeUnitBounds(),
+ mnPriority( nPrio ),
+ maBounds( rSrc.maBounds ),
+ mpAttributeLayer(),
+ mpIntrinsicAnimationActivity(),
+ mnAttributeTransformationState(0),
+ mnAttributeClipState(0),
+ mnAttributeAlphaState(0),
+ mnAttributePositionState(0),
+ mnAttributeContentState(0),
+ mnAttributeVisibilityState(0),
+ maViewShapes(),
+ mxComponentContext( rSrc.mxComponentContext ),
+ maHyperlinkIndices(),
+ maHyperlinkRegions(),
+ maSubsetting( rTreeNode, mpCurrMtf ),
+ mnIsAnimatedCount(0),
+ mnAnimationLoopCount(0),
+ meCycleMode(CYCLE_LOOP),
+ mbIsVisible( rSrc.mbIsVisible ),
+ mbForceUpdate( false ),
+ mbAttributeLayerRevoked( false ),
+ mbDrawingLayerAnim( false )
+ {
+ ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" );
+ ENSURE_OR_THROW( mpCurrMtf, "DrawShape::DrawShape(): Invalid metafile" );
+
+ // xxx todo: currently not implemented for subsetted shapes;
+ // would mean modifying set of hyperlink regions when
+ // subsetting text portions. N.B.: there's already an
+ // issue for this #i72828#
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ //
+ // Public methods
+ //
+ //////////////////////////////////////////////////////////////////////
+
+ DrawShapeSharedPtr DrawShape::create(
+ const uno::Reference< drawing::XShape >& xShape,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ bool bForeignSource,
+ const SlideShowContext& rContext )
+ {
+ DrawShapeSharedPtr pShape( new DrawShape(xShape,
+ xContainingPage,
+ nPrio,
+ bForeignSource,
+ rContext) );
+
+ if( pShape->hasIntrinsicAnimation() )
+ {
+ OSL_ASSERT( pShape->maAnimationFrames.empty() );
+ if( pShape->getNumberOfTreeNodes(
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH) > 0 )
+ {
+ pShape->mpIntrinsicAnimationActivity =
+ createDrawingLayerAnimActivity(
+ rContext,
+ pShape);
+ }
+ }
+
+ if( pShape->hasHyperlinks() )
+ rContext.mpSubsettableShapeManager->addHyperlinkArea( pShape );
+
+ return pShape;
+ }
+
+ DrawShapeSharedPtr DrawShape::create(
+ const uno::Reference< drawing::XShape >& xShape,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ const Graphic& rGraphic,
+ const SlideShowContext& rContext )
+ {
+ DrawShapeSharedPtr pShape( new DrawShape(xShape,
+ xContainingPage,
+ nPrio,
+ rGraphic,
+ rContext) );
+
+ if( pShape->hasIntrinsicAnimation() )
+ {
+ OSL_ASSERT( !pShape->maAnimationFrames.empty() );
+
+ std::vector<double> aTimeout;
+ std::transform(
+ pShape->maAnimationFrames.begin(),
+ pShape->maAnimationFrames.end(),
+ std::back_insert_iterator< std::vector<double> >( aTimeout ),
+ boost::mem_fn(&MtfAnimationFrame::getDuration) );
+
+ WakeupEventSharedPtr pWakeupEvent(
+ new WakeupEvent( rContext.mrEventQueue.getTimer(),
+ rContext.mrActivitiesQueue ) );
+
+ ActivitySharedPtr pActivity =
+ createIntrinsicAnimationActivity(
+ rContext,
+ pShape,
+ pWakeupEvent,
+ aTimeout,
+ pShape->mnAnimationLoopCount,
+ pShape->meCycleMode);
+
+ pWakeupEvent->setActivity( pActivity );
+ pShape->mpIntrinsicAnimationActivity = pActivity;
+ }
+
+ OSL_ENSURE( !pShape->hasHyperlinks(),
+ "DrawShape::create(): graphic-only shapes must not have hyperlinks!" );
+
+ return pShape;
+ }
+
+ DrawShape::~DrawShape()
+ {
+ try
+ {
+ // dispose intrinsic animation activity, else, it will
+ // linger forever
+ ActivitySharedPtr pActivity( mpIntrinsicAnimationActivity.lock() );
+ if( pActivity )
+ pActivity->dispose();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ uno::Reference< drawing::XShape > DrawShape::getXShape() const
+ {
+ return mxShape;
+ }
+
+ void DrawShape::addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer )
+ {
+ ViewShapeVector::iterator aEnd( maViewShapes.end() );
+
+ // already added?
+ if( ::std::find_if( maViewShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rNewLayer ) ) ) != aEnd )
+ {
+ // yes, nothing to do
+ return;
+ }
+
+ ViewShapeSharedPtr pNewShape( new ViewShape( rNewLayer ) );
+
+ maViewShapes.push_back( pNewShape );
+
+ // pass on animation state
+ if( mnIsAnimatedCount )
+ {
+ for( int i=0; i<mnIsAnimatedCount; ++i )
+ pNewShape->enterAnimationMode();
+ }
+
+ // render the Shape on the newly added ViewLayer
+ if( bRedrawLayer )
+ {
+ pNewShape->update( mpCurrMtf,
+ getViewRenderArgs(),
+ ViewShape::FORCE,
+ isVisible() );
+ }
+ }
+
+ bool DrawShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
+ {
+ const ViewShapeVector::iterator aEnd( maViewShapes.end() );
+
+ OSL_ENSURE( ::std::count_if(maViewShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rLayer ) ) ) < 2,
+ "DrawShape::removeViewLayer(): Duplicate ViewLayer entries!" );
+
+ ViewShapeVector::iterator aIter;
+
+ if( (aIter=::std::remove_if( maViewShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rLayer ) ) )) == aEnd )
+ {
+ // view layer seemingly was not added, failed
+ return false;
+ }
+
+ // actually erase from container
+ maViewShapes.erase( aIter, aEnd );
+
+ return true;
+ }
+
+ bool DrawShape::clearAllViewLayers()
+ {
+ maViewShapes.clear();
+ return true;
+ }
+
+ bool DrawShape::update() const
+ {
+ if( mbForceUpdate )
+ {
+ return render();
+ }
+ else
+ {
+ return implRender( getUpdateFlags() );
+ }
+ }
+
+ bool DrawShape::render() const
+ {
+ // force redraw. Have to also pass on the update flags,
+ // because e.g. content update (regeneration of the
+ // metafile renderer) is normally not performed. A simple
+ // ViewShape::FORCE would only paint the metafile in its
+ // old state.
+ return implRender( ViewShape::FORCE | getUpdateFlags() );
+ }
+
+ bool DrawShape::isContentChanged() const
+ {
+ return mbForceUpdate ?
+ true :
+ getUpdateFlags() != ViewShape::NONE;
+ }
+
+
+ ::basegfx::B2DRectangle DrawShape::getBounds() const
+ {
+ // little optimization: for non-modified shapes, we don't
+ // create an ShapeAttributeStack, and therefore also don't
+ // have to check it.
+ return getShapePosSize( maBounds,
+ mpAttributeLayer );
+ }
+
+ ::basegfx::B2DRectangle DrawShape::getDomBounds() const
+ {
+ return maBounds;
+ }
+
+ namespace
+ {
+ /** Functor expanding AA border for each passed ViewShape
+
+ Could not use ::boost::bind here, since
+ B2DRange::expand is overloaded (which yields one or
+ the other template type deduction ambiguous)
+ */
+ class Expander
+ {
+ public:
+ Expander( ::basegfx::B2DSize& rBounds ) :
+ mrBounds( rBounds )
+ {
+ }
+
+ void operator()( const ViewShapeSharedPtr& rShape ) const
+ {
+ const ::basegfx::B2DSize& rShapeBorder( rShape->getAntialiasingBorder() );
+
+ mrBounds.setX(
+ ::std::max(
+ rShapeBorder.getX(),
+ mrBounds.getX() ) );
+ mrBounds.setY(
+ ::std::max(
+ rShapeBorder.getY(),
+ mrBounds.getY() ) );
+ }
+
+ private:
+ ::basegfx::B2DSize& mrBounds;
+ };
+ }
+
+ ::basegfx::B2DRectangle DrawShape::getUpdateArea() const
+ {
+ ::basegfx::B2DRectangle aBounds;
+
+ // an already empty shape bound need no further
+ // treatment. In fact, any changes applied below would
+ // actually remove the special empty state, thus, don't
+ // change!
+ if( !maBounds.isEmpty() )
+ {
+ basegfx::B2DRectangle aUnitBounds(0.0,0.0,1.0,1.0);
+
+ if( !maViewShapes.empty() )
+ aUnitBounds = getActualUnitShapeBounds();
+
+ if( !aUnitBounds.isEmpty() )
+ {
+ if( mpAttributeLayer )
+ {
+ // calc actual shape area (in user coordinate
+ // space) from the transformation as given by the
+ // shape attribute layer
+ aBounds = getShapeUpdateArea( aUnitBounds,
+ getShapeTransformation( getBounds(),
+ mpAttributeLayer ),
+ mpAttributeLayer );
+ }
+ else
+ {
+ // no attribute layer, thus, the true shape bounds
+ // can be directly derived from the XShape bound
+ // attribute
+ aBounds = getShapeUpdateArea( aUnitBounds,
+ maBounds );
+ }
+
+ if( !maViewShapes.empty() )
+ {
+ // determine border needed for antialiasing the shape
+ ::basegfx::B2DSize aAABorder(0.0,0.0);
+
+ // for every view, get AA border and 'expand' aAABorder
+ // appropriately.
+ ::std::for_each( maViewShapes.begin(),
+ maViewShapes.end(),
+ Expander( aAABorder ) );
+
+ // add calculated AA border to aBounds
+ aBounds = ::basegfx::B2DRectangle( aBounds.getMinX() - aAABorder.getX(),
+ aBounds.getMinY() - aAABorder.getY(),
+ aBounds.getMaxX() + aAABorder.getX(),
+ aBounds.getMaxY() + aAABorder.getY() );
+ }
+ }
+ }
+
+ return aBounds;
+ }
+
+ bool DrawShape::isVisible() const
+ {
+ bool bIsVisible( mbIsVisible );
+
+ if( mpAttributeLayer )
+ {
+ // check whether visibility and alpha are not default
+ // (mpAttributeLayer->isVisibilityValid() returns true
+ // then): bVisible becomes true, if shape visibility
+ // is on and alpha is not 0.0 (fully transparent)
+ if( mpAttributeLayer->isVisibilityValid() )
+ bIsVisible = mpAttributeLayer->getVisibility();
+
+ // only touch bIsVisible, if the shape is still
+ // visible - if getVisibility already made us
+ // invisible, no alpha value will make us appear
+ // again.
+ if( bIsVisible && mpAttributeLayer->isAlphaValid() )
+ bIsVisible = !::basegfx::fTools::equalZero( mpAttributeLayer->getAlpha() );
+ }
+
+ return bIsVisible;
+ }
+
+ double DrawShape::getPriority() const
+ {
+ return mnPriority;
+ }
+
+ bool DrawShape::isBackgroundDetached() const
+ {
+ return mnIsAnimatedCount > 0;
+ }
+
+ bool DrawShape::hasIntrinsicAnimation() const
+ {
+ return (!maAnimationFrames.empty() || mbDrawingLayerAnim);
+ }
+
+ bool DrawShape::setIntrinsicAnimationFrame( ::std::size_t nCurrFrame )
+ {
+ ENSURE_OR_RETURN_FALSE( nCurrFrame < maAnimationFrames.size(),
+ "DrawShape::setIntrinsicAnimationFrame(): frame index out of bounds" );
+
+ if( mnCurrFrame != nCurrFrame )
+ {
+ mnCurrFrame = nCurrFrame;
+ mpCurrMtf = maAnimationFrames[ mnCurrFrame ].mpMtf;
+ mbForceUpdate = true;
+ }
+
+ return true;
+ }
+
+ // hyperlink support
+ void DrawShape::prepareHyperlinkIndices() const
+ {
+ if ( !maHyperlinkIndices.empty())
+ {
+ maHyperlinkIndices.clear();
+ maHyperlinkRegions.clear();
+ }
+
+ sal_Int32 nIndex = 0;
+ for ( MetaAction * pCurrAct = mpCurrMtf->FirstAction();
+ pCurrAct != 0; pCurrAct = mpCurrMtf->NextAction() )
+ {
+ if (pCurrAct->GetType() == META_COMMENT_ACTION) {
+ MetaCommentAction * pAct =
+ static_cast<MetaCommentAction *>(pCurrAct);
+ // skip comment if not a special XTEXT comment
+ if (pAct->GetComment().CompareIgnoreCaseToAscii(
+ RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_BEGIN") ) ==
+ COMPARE_EQUAL &&
+ // e.g. date field doesn't have data!
+ // currently assuming that only url field, this is
+ // somehow fragile! xxx todo if possible
+ pAct->GetData() != 0 &&
+ pAct->GetDataSize() > 0)
+ {
+ if (!maHyperlinkIndices.empty() &&
+ maHyperlinkIndices.back().second == -1) {
+ OSL_ENSURE( false, "### pending FIELD_SEQ_END!" );
+ maHyperlinkIndices.pop_back();
+ maHyperlinkRegions.pop_back();
+ }
+ maHyperlinkIndices.push_back(
+ HyperlinkIndexPair( nIndex + 1,
+ -1 /* to be filled below */ ) );
+ maHyperlinkRegions.push_back(
+ HyperlinkRegion(
+ basegfx::B2DRectangle(),
+ rtl::OUString(
+ reinterpret_cast<sal_Unicode const*>(
+ pAct->GetData()),
+ pAct->GetDataSize() / sizeof(sal_Unicode) )
+ ) );
+ }
+ else if (pAct->GetComment().CompareIgnoreCaseToAscii(
+ RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_END")) ==
+ COMPARE_EQUAL &&
+ // pending end is expected:
+ !maHyperlinkIndices.empty() &&
+ maHyperlinkIndices.back().second == -1)
+ {
+ maHyperlinkIndices.back().second = nIndex;
+ }
+ ++nIndex;
+ }
+ else
+ nIndex += getNextActionOffset(pCurrAct);
+ }
+ if (!maHyperlinkIndices.empty() &&
+ maHyperlinkIndices.back().second == -1) {
+ OSL_ENSURE( false, "### pending FIELD_SEQ_END!" );
+ maHyperlinkIndices.pop_back();
+ maHyperlinkRegions.pop_back();
+ }
+ OSL_ASSERT( maHyperlinkIndices.size() == maHyperlinkRegions.size());
+ }
+
+ bool DrawShape::hasHyperlinks() const
+ {
+ return ! maHyperlinkRegions.empty();
+ }
+
+ HyperlinkArea::HyperlinkRegions DrawShape::getHyperlinkRegions() const
+ {
+ OSL_ASSERT( !maViewShapes.empty() );
+
+ if( !isVisible() )
+ return HyperlinkArea::HyperlinkRegions();
+
+ // late init, determine regions:
+ if( !maHyperlinkRegions.empty() &&
+ !maViewShapes.empty() &&
+ // region already inited?
+ maHyperlinkRegions.front().first.getWidth() == 0 &&
+ maHyperlinkRegions.front().first.getHeight() == 0 &&
+ maHyperlinkRegions.size() == maHyperlinkIndices.size() )
+ {
+ // TODO(Q2): Although this _is_ currently
+ // view-agnostic, it might not stay like that.
+ ViewShapeSharedPtr const& pViewShape = maViewShapes.front();
+ cppcanvas::CanvasSharedPtr const pCanvas(
+ pViewShape->getViewLayer()->getCanvas() );
+
+ // reuse Renderer of first view shape:
+ cppcanvas::RendererSharedPtr const pRenderer(
+ pViewShape->getRenderer(
+ pCanvas, mpCurrMtf, mpAttributeLayer ) );
+
+ OSL_ASSERT( pRenderer );
+
+ if (pRenderer)
+ {
+ basegfx::B2DHomMatrix const aOldTransform(
+ pCanvas->getTransformation() );
+ basegfx::B2DHomMatrix aTransform;
+ pCanvas->setTransformation( aTransform /* empty */ );
+
+ comphelper::ScopeGuard const resetOldTransformation(
+ boost::bind( &cppcanvas::Canvas::setTransformation,
+ pCanvas.get(),
+ boost::cref(aOldTransform) ));
+
+ aTransform.scale( maBounds.getWidth(),
+ maBounds.getHeight() );
+ pRenderer->setTransformation( aTransform );
+ pRenderer->setClip();
+
+ for( std::size_t pos = maHyperlinkRegions.size(); pos--; )
+ {
+ // get region:
+ HyperlinkIndexPair const& rIndices = maHyperlinkIndices[pos];
+ basegfx::B2DRectangle const region(
+ pRenderer->getSubsetArea( rIndices.first,
+ rIndices.second ));
+ maHyperlinkRegions[pos].first = region;
+ }
+ }
+ }
+
+ // shift shape-relative hyperlink regions to
+ // slide-absolute position
+
+ HyperlinkRegions aTranslatedRegions;
+ const basegfx::B2DPoint& rOffset(getBounds().getMinimum());
+ HyperlinkRegions::const_iterator aIter( maHyperlinkRegions.begin() );
+ HyperlinkRegions::const_iterator const aEnd ( maHyperlinkRegions.end() );
+ while( aIter != aEnd )
+ {
+ basegfx::B2DRange const& relRegion( aIter->first );
+ aTranslatedRegions.push_back(
+ std::make_pair(
+ basegfx::B2DRange(
+ relRegion.getMinimum() + rOffset,
+ relRegion.getMaximum() + rOffset),
+ aIter->second) );
+ ++aIter;
+ }
+
+ return aTranslatedRegions;
+ }
+
+ double DrawShape::getHyperlinkPriority() const
+ {
+ return getPriority();
+ }
+
+
+ // AnimatableShape methods
+ // ======================================================
+
+ void DrawShape::enterAnimationMode()
+ {
+ OSL_ENSURE( !maViewShapes.empty(),
+ "DrawShape::enterAnimationMode(): called on DrawShape without views" );
+
+ if( mnIsAnimatedCount == 0 )
+ {
+ // notify all ViewShapes, by calling their enterAnimationMode method.
+ // We're now entering animation mode
+ ::std::for_each( maViewShapes.begin(),
+ maViewShapes.end(),
+ ::boost::mem_fn( &ViewShape::enterAnimationMode ) );
+ }
+
+ ++mnIsAnimatedCount;
+ }
+
+ void DrawShape::leaveAnimationMode()
+ {
+ OSL_ENSURE( !maViewShapes.empty(),
+ "DrawShape::leaveAnimationMode(): called on DrawShape without views" );
+
+ --mnIsAnimatedCount;
+
+ if( mnIsAnimatedCount == 0 )
+ {
+ // notify all ViewShapes, by calling their leaveAnimationMode method.
+ // we're now leaving animation mode
+ ::std::for_each( maViewShapes.begin(),
+ maViewShapes.end(),
+ ::boost::mem_fn( &ViewShape::leaveAnimationMode ) );
+ }
+ }
+
+
+ // AttributableShape methods
+ // ======================================================
+
+ ShapeAttributeLayerSharedPtr DrawShape::createAttributeLayer()
+ {
+ // create new layer, with last as its new child
+ mpAttributeLayer.reset( new ShapeAttributeLayer( mpAttributeLayer ) );
+
+ // Update the local state ids to reflect those of the new layer.
+ updateStateIds();
+
+ return mpAttributeLayer;
+ }
+
+ bool DrawShape::revokeAttributeLayer( const ShapeAttributeLayerSharedPtr& rLayer )
+ {
+ if( !mpAttributeLayer )
+ return false; // no layers
+
+ if( mpAttributeLayer == rLayer )
+ {
+ // it's the toplevel layer
+ mpAttributeLayer = mpAttributeLayer->getChildLayer();
+
+ // force content redraw, all state variables have
+ // possibly changed
+ mbAttributeLayerRevoked = true;
+
+ return true;
+ }
+ else
+ {
+ // pass on to the layer, to try its children
+ return mpAttributeLayer->revokeChildLayer( rLayer );
+ }
+ }
+
+ ShapeAttributeLayerSharedPtr DrawShape::getTopmostAttributeLayer() const
+ {
+ return mpAttributeLayer;
+ }
+
+ void DrawShape::setVisibility( bool bVisible )
+ {
+ if( mbIsVisible != bVisible )
+ {
+ mbIsVisible = bVisible;
+ mbForceUpdate = true;
+ }
+ }
+
+ const DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier() const
+ {
+ return *this;
+ }
+
+ DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier()
+ {
+ return *this;
+ }
+
+ DocTreeNode DrawShape::getSubsetNode() const
+ {
+ ensureVerboseMtfComments();
+
+ // forward to delegate
+ return maSubsetting.getSubsetNode();
+ }
+
+ AttributableShapeSharedPtr DrawShape::getSubset( const DocTreeNode& rTreeNode ) const
+ {
+ ENSURE_OR_THROW( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0,
+ "DrawShape::getSubset(): subset query on shape with apparently no subsets" );
+
+ // forward to delegate
+ return maSubsetting.getSubsetShape( rTreeNode );
+ }
+
+ bool DrawShape::createSubset( AttributableShapeSharedPtr& o_rSubset,
+ const DocTreeNode& rTreeNode )
+ {
+ ENSURE_OR_THROW( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0,
+ "DrawShape::createSubset(): subset query on shape with apparently no subsets" );
+
+ // subset shape already created for this DocTreeNode?
+ AttributableShapeSharedPtr pSubset( maSubsetting.getSubsetShape( rTreeNode ) );
+
+ // when true, this method has created a new subset
+ // DrawShape
+ bool bNewlyCreated( false );
+
+ if( pSubset )
+ {
+ o_rSubset = pSubset;
+
+ // reusing existing subset
+ }
+ else
+ {
+ // not yet created, init entry
+ o_rSubset.reset( new DrawShape( *this,
+ rTreeNode,
+ // TODO(Q3): That's a
+ // hack. We assume
+ // that start and end
+ // index will always
+ // be less than 65535
+ mnPriority +
+ rTreeNode.getStartIndex()/double(SAL_MAX_INT16) ));
+
+ bNewlyCreated = true; // subset newly created
+ }
+
+ // always register shape at DrawShapeSubsetting, to keep
+ // refcount up-to-date
+ maSubsetting.addSubsetShape( o_rSubset );
+
+ // flush bounds cache
+ maCurrentShapeUnitBounds.reset();
+
+ return bNewlyCreated;
+ }
+
+ bool DrawShape::revokeSubset( const AttributableShapeSharedPtr& rShape )
+ {
+ ENSURE_OR_THROW( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0,
+ "DrawShape::createSubset(): subset query on shape with apparently no subsets" );
+
+ // flush bounds cache
+ maCurrentShapeUnitBounds.reset();
+
+ // forward to delegate
+ if( maSubsetting.revokeSubsetShape( rShape ) )
+ {
+ // force redraw, our content has possibly changed (as
+ // one of the subsets now display within our shape
+ // again).
+ mbForceUpdate = true;
+
+ // #i47428# TEMP FIX: synchronize visibility of subset
+ // with parent.
+
+ // TODO(F3): Remove here, and implement
+ // TEXT_ONLY/BACKGROUND_ONLY with the proverbial
+ // additional level of indirection: create a
+ // persistent subset, containing all text/only the
+ // background respectively. From _that_ object,
+ // generate the temporary character subset shapes.
+ const ShapeAttributeLayerSharedPtr& rAttrLayer(
+ rShape->getTopmostAttributeLayer() );
+ if( rAttrLayer &&
+ rAttrLayer->isVisibilityValid() &&
+ rAttrLayer->getVisibility() != isVisible() )
+ {
+ const bool bVisibility( rAttrLayer->getVisibility() );
+
+ // visibilities differ - adjust ours, then
+ if( mpAttributeLayer )
+ mpAttributeLayer->setVisibility( bVisibility );
+ else
+ mbIsVisible = bVisibility;
+ }
+
+ // END TEMP FIX
+
+ return true;
+ }
+
+ return false;
+ }
+
+ sal_Int32 DrawShape::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
+ {
+ ensureVerboseMtfComments();
+
+ return maSubsetting.getNumberOfTreeNodes( eNodeType );
+ }
+
+ DocTreeNode DrawShape::getTreeNode( sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
+ {
+ ensureVerboseMtfComments();
+
+ if ( hasHyperlinks())
+ {
+ prepareHyperlinkIndices();
+ }
+
+ return maSubsetting.getTreeNode( nNodeIndex, eNodeType );
+ }
+
+ sal_Int32 DrawShape::getNumberOfSubsetTreeNodes ( const DocTreeNode& rParentNode,
+ DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
+ {
+ ensureVerboseMtfComments();
+
+ return maSubsetting.getNumberOfSubsetTreeNodes( rParentNode, eNodeType );
+ }
+
+ DocTreeNode DrawShape::getSubsetTreeNode( const DocTreeNode& rParentNode,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException
+ {
+ ensureVerboseMtfComments();
+
+ return maSubsetting.getSubsetTreeNode( rParentNode, nNodeIndex, eNodeType );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawshape.hxx b/slideshow/source/engine/shapes/drawshape.hxx
new file mode 100644
index 000000000000..f7235dd7d87d
--- /dev/null
+++ b/slideshow/source/engine/shapes/drawshape.hxx
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DRAWSHAPE_HXX
+#define INCLUDED_SLIDESHOW_DRAWSHAPE_HXX
+
+#include <osl/diagnose.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+
+#include "attributableshape.hxx"
+#include "doctreenodesupplier.hxx"
+#include "gdimtftools.hxx"
+#include "viewshape.hxx"
+#include "hyperlinkarea.hxx"
+
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <set>
+#include <vector>
+
+class Graphic;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class Activity;
+ struct SlideShowContext;
+ class DrawShapeSubsetting;
+ class DrawShape;
+ typedef ::boost::shared_ptr< DrawShape > DrawShapeSharedPtr;
+
+ /** This class is the representation of a draw document's
+ XShape, and implements the Shape, AnimatableShape, and
+ AttributableShape interfaces.
+
+ @attention this class is to be treated 'final', i.e. one
+ should not derive from it.
+ */
+ class DrawShape : public AttributableShape,
+ public DocTreeNodeSupplier,
+ public HyperlinkArea,
+ protected ::osl::DebugBase<DrawShape>
+ {
+ public:
+ /** Create a shape for the given XShape
+
+ @param xShape
+ The XShape to represent.
+
+ @param xContainingPage
+ The page that contains this shape. Needed for proper
+ import (currently, the UnoGraphicExporter needs this
+ information).
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+
+ @param bForeignSource
+ When true, the source of the shape metafile might be a
+ foreign application. The metafile is checked against
+ unsupported content, and, if necessary, returned as a
+ pre-rendererd bitmap.
+ */
+ static DrawShapeSharedPtr create(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ bool bForeignSource,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ /** Create a shape for the given XShape and graphic content
+
+ @param xShape
+ The XShape to represent.
+
+ @param xContainingPage
+ The page that contains this shape. Needed for proper
+ import (currently, the UnoGraphicExporter needs this
+ information).
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+
+ @param rGraphic
+ Graphic to display in the shape's bound rect. If this
+ Graphic contains animatable content, the created
+ DrawShape will register itself for intrinsic animation
+ events.
+ */
+ static DrawShapeSharedPtr create(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ const Graphic& rGraphic,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > getXShape() const;
+
+ virtual ~DrawShape();
+
+
+ // View layer methods
+ //------------------------------------------------------------------
+
+ virtual void addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer );
+ virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer );
+ virtual bool clearAllViewLayers();
+
+ // attribute methods
+ //------------------------------------------------------------------
+
+ virtual ShapeAttributeLayerSharedPtr createAttributeLayer();
+ virtual bool revokeAttributeLayer( const ShapeAttributeLayerSharedPtr& rLayer );
+ virtual ShapeAttributeLayerSharedPtr getTopmostAttributeLayer() const;
+ virtual void setVisibility( bool bVisible );
+ virtual ::basegfx::B2DRectangle getBounds() const;
+ virtual ::basegfx::B2DRectangle getDomBounds() const;
+ virtual ::basegfx::B2DRectangle getUpdateArea() const;
+ virtual bool isVisible() const;
+ virtual double getPriority() const;
+
+
+ // animation methods
+ //------------------------------------------------------------------
+
+ virtual void enterAnimationMode();
+ virtual void leaveAnimationMode();
+ virtual bool isBackgroundDetached() const;
+
+ // render methods
+ //------------------------------------------------------------------
+
+ virtual bool update() const;
+ virtual bool render() const;
+ virtual bool isContentChanged() const;
+
+ // Sub item specialities
+ //------------------------------------------------------------------
+
+ virtual const DocTreeNodeSupplier& getTreeNodeSupplier() const;
+ virtual DocTreeNodeSupplier& getTreeNodeSupplier();
+
+ virtual DocTreeNode getSubsetNode() const;
+ virtual AttributableShapeSharedPtr getSubset( const DocTreeNode& rTreeNode ) const;
+ virtual bool createSubset( AttributableShapeSharedPtr& o_rSubset,
+ const DocTreeNode& rTreeNode );
+ virtual bool revokeSubset( const AttributableShapeSharedPtr& rShape );
+
+
+ // DocTreeNodeSupplier methods
+ //------------------------------------------------------------------
+
+ virtual sal_Int32 getNumberOfTreeNodes ( DocTreeNode::NodeType eNodeType ) const; // throw ShapeLoadFailedException;
+ virtual DocTreeNode getTreeNode ( sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const; // throw ShapeLoadFailedException;
+ virtual sal_Int32 getNumberOfSubsetTreeNodes ( const DocTreeNode& rParentNode,
+ DocTreeNode::NodeType eNodeType ) const; // throw ShapeLoadFailedException;
+ virtual DocTreeNode getSubsetTreeNode ( const DocTreeNode& rParentNode,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const; // throw ShapeLoadFailedException;
+
+ // HyperlinkArea methods
+ //------------------------------------------------------------------
+
+ virtual HyperlinkRegions getHyperlinkRegions() const;
+ virtual double getHyperlinkPriority() const;
+
+
+ // intrinsic animation methods
+ //------------------------------------------------------------------
+
+ /** Display next frame of an intrinsic animation.
+
+ Used by IntrinsicAnimationActivity, to show the next
+ animation frame.
+ */
+ bool setIntrinsicAnimationFrame( ::std::size_t nCurrFrame );
+
+ /** forces the drawshape to load and return a specially
+ crafted metafile, usable to display drawing layer text
+ animations.
+ */
+ GDIMetaFileSharedPtr forceScrollTextMetaFile();
+
+ private:
+ /** Create a shape for the given XShape
+
+ @param xShape
+ The XShape to represent.
+
+ @param xContainingPage
+ The page that contains this shape. Needed for proper
+ import (currently, the UnoGraphicExporter needs this
+ information).
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+
+ @param bForeignSource
+ When true, the source of the shape metafile might be a
+ foreign application. The metafile is checked against
+ unsupported content, and, if necessary, returned as a
+ pre-rendererd bitmap.
+ */
+ DrawShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ bool bForeignSource,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ /** Create a shape for the given XShape and graphic content
+
+ @param xShape
+ The XShape to represent.
+
+ @param xContainingPage
+ The page that contains this shape. Needed for proper
+ import (currently, the UnoGraphicExporter needs this
+ information).
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+
+ @param rGraphic
+ Graphic to display in the shape's bound rect. If this
+ Graphic contains animatable content, the created
+ DrawShape will register itself for intrinsic animation
+ events.
+ */
+ DrawShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xContainingPage,
+ double nPrio,
+ const Graphic& rGraphic,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ /** Private copy constructor
+
+ Used to create subsetted shapes
+ */
+ DrawShape( const DrawShape&, const DocTreeNode& rTreeNode, double nPrio );
+
+ int getUpdateFlags() const;
+ bool implRender( int nUpdateFlags ) const;
+ void updateStateIds() const;
+
+ ViewShape::RenderArgs getViewRenderArgs() const;
+ ::basegfx::B2DRectangle getActualUnitShapeBounds() const;
+
+ void ensureVerboseMtfComments() const;
+ bool hasIntrinsicAnimation() const;
+ bool hasHyperlinks() const;
+ void prepareHyperlinkIndices() const;
+
+ /// The associated XShape
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > mxShape;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage > mxPage;
+
+ /** A vector of metafiles actually representing the Shape.
+
+ If this shape is not animated, only a single entry is
+ available.
+ */
+ mutable VectorOfMtfAnimationFrames maAnimationFrames;
+ ::std::size_t mnCurrFrame;
+
+ /// Metafile of currently active frame (static for shapes w/o intrinsic animation)
+ mutable GDIMetaFileSharedPtr mpCurrMtf;
+
+ /// loadflags of current meta file
+ mutable int mnCurrMtfLoadFlags;
+
+ /// Contains the current shape bounds, in unit rect space
+ mutable ::boost::optional<basegfx::B2DRectangle> maCurrentShapeUnitBounds;
+
+ // The attributes of this Shape
+ const double mnPriority;
+ ::basegfx::B2DRectangle maBounds; // always needed for rendering.
+ // for subset shapes, this member
+ // might change when views are
+ // added, as minimal bounds are
+ // calculated
+
+ // Pointer to modifiable shape attributes
+ ShapeAttributeLayerSharedPtr mpAttributeLayer; // only created lazily
+
+ // held here, to signal our destruction
+ boost::weak_ptr<Activity> mpIntrinsicAnimationActivity;
+
+ // The attribute states, to detect attribute changes,
+ // without buffering and querying each single attribute
+ mutable State::StateId mnAttributeTransformationState;
+ mutable State::StateId mnAttributeClipState;
+ mutable State::StateId mnAttributeAlphaState;
+ mutable State::StateId mnAttributePositionState;
+ mutable State::StateId mnAttributeContentState;
+ mutable State::StateId mnAttributeVisibilityState;
+
+ /// the list of active view shapes (one for each registered view layer)
+ typedef ::std::vector< ViewShapeSharedPtr > ViewShapeVector;
+ ViewShapeVector maViewShapes;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext> mxComponentContext;
+
+ /// hyperlink support
+ typedef ::std::pair<sal_Int32 /* mtf start */,
+ sal_Int32 /* mtf end */> HyperlinkIndexPair;
+ typedef ::std::vector<HyperlinkIndexPair> HyperlinkIndexPairVector;
+ mutable HyperlinkIndexPairVector maHyperlinkIndices;
+ mutable HyperlinkRegions maHyperlinkRegions;
+
+ /// Delegated subset handling
+ mutable DrawShapeSubsetting maSubsetting;
+
+ /// Whether this shape is currently in animation mode (value != 0)
+ int mnIsAnimatedCount;
+
+ /// Number of times the bitmap animation shall loop
+ ::std::size_t mnAnimationLoopCount;
+
+ /// Cycle mode for bitmap animation
+ CycleMode meCycleMode;
+
+ /// Whether shape is visible (without attribute layers)
+ bool mbIsVisible;
+
+ /// Whether redraw is necessary, regardless of state ids
+ mutable bool mbForceUpdate;
+
+ /// Whether attribute layer was revoked (making a redraw necessary)
+ mutable bool mbAttributeLayerRevoked;
+
+ /// whether a drawing layer animation has to be performed
+ bool mbDrawingLayerAnim;
+
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_DRAWSHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawshapesubsetting.cxx b/slideshow/source/engine/shapes/drawshapesubsetting.cxx
new file mode 100644
index 000000000000..889e9566c76e
--- /dev/null
+++ b/slideshow/source/engine/shapes/drawshapesubsetting.cxx
@@ -0,0 +1,868 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <rtl/math.hxx>
+#include <rtl/logfile.hxx>
+
+#include <vcl/metaact.hxx>
+#include <vcl/gdimtf.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include "drawshapesubsetting.hxx"
+#include "drawshape.hxx"
+
+#include <boost/bind.hpp>
+
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ //////////////////////////////////////////////////////////////////////
+ //
+ // Private methods
+ //
+ //////////////////////////////////////////////////////////////////////
+
+ void DrawShapeSubsetting::ensureInitializedNodeTree() const
+ {
+ ENSURE_OR_THROW( mpMtf,
+ "DrawShapeSubsetting::ensureInitializedNodeTree(): Invalid mtf" );
+
+ if( mbNodeTreeInitialized )
+ return; // done, already initialized.
+
+ // init doctree vector
+ maActionClassVector.clear();
+ maActionClassVector.reserve( mpMtf->GetActionCount() );
+
+ // search metafile for text output
+ MetaAction* pCurrAct;
+
+ sal_Int32 nActionIndex(0);
+ sal_Int32 nLastTextActionIndex(0);
+ for( pCurrAct = mpMtf->FirstAction(); pCurrAct; pCurrAct = mpMtf->NextAction() )
+ {
+ // check for one of our special text doctree comments
+ switch( pCurrAct->GetType() )
+ {
+ case META_COMMENT_ACTION:
+ {
+ MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pCurrAct);
+
+ // skip comment if not a special XTEXT comment
+ if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT", 5 ) == COMPARE_EQUAL )
+ {
+ // fill classification vector with NOOPs,
+ // then insert corresponding classes at
+ // the given index
+ maActionClassVector.resize( nActionIndex+1, CLASS_NOOP );
+
+ if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOC" ) == COMPARE_EQUAL )
+ {
+ // special, because can happen
+ // in-between of portions - set
+ // character-end classificator at
+ // given index (relative to last text
+ // action).
+ const sal_Int32 nIndex( nLastTextActionIndex + pAct->GetValue() );
+
+ ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex) < maActionClassVector.size(),
+ "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
+
+ maActionClassVector[ nIndex ] = CLASS_CHARACTER_CELL_END;
+ }
+ else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOW" ) == COMPARE_EQUAL )
+ {
+ // special, because can happen
+ // in-between of portions - set
+ // word-end classificator at given
+ // index (relative to last text
+ // action).
+ const sal_Int32 nIndex( nLastTextActionIndex + pAct->GetValue() );
+
+ ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex) < maActionClassVector.size(),
+ "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
+
+ maActionClassVector[ nIndex ] = CLASS_WORD_END;
+ }
+ else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOS" ) == COMPARE_EQUAL )
+ {
+ // special, because can happen
+ // in-between of portions - set
+ // sentence-end classificator at given
+ // index (relative to last text
+ // action).
+ const sal_Int32 nIndex( nLastTextActionIndex + pAct->GetValue() );
+
+ ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex) < maActionClassVector.size(),
+ "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
+
+ maActionClassVector[ nIndex ] = CLASS_SENTENCE_END;
+ }
+ else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOL" ) == COMPARE_EQUAL )
+ {
+ maActionClassVector[ nActionIndex ] = CLASS_LINE_END;
+ }
+ else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOP" ) == COMPARE_EQUAL )
+ {
+ maActionClassVector[ nActionIndex ] = CLASS_PARAGRAPH_END;
+ }
+ else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_PAINTSHAPE_END" ) == COMPARE_EQUAL )
+ {
+ maActionClassVector[ nActionIndex ] = CLASS_SHAPE_END;
+ }
+ else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_PAINTSHAPE_BEGIN" ) == COMPARE_EQUAL )
+ {
+ maActionClassVector[ nActionIndex ] = CLASS_SHAPE_START;
+ }
+ }
+ ++nActionIndex;
+ break;
+ }
+ case META_TEXT_ACTION:
+ case META_TEXTARRAY_ACTION:
+ case META_STRETCHTEXT_ACTION:
+ nLastTextActionIndex = nActionIndex;
+ // fallthrough intended
+ default:
+ // comment action and all actions not
+ // explicitely handled here:
+ nActionIndex += getNextActionOffset(pCurrAct);
+ break;
+ }
+ }
+
+ mbNodeTreeInitialized = true;
+ }
+
+ void DrawShapeSubsetting::updateSubsetBounds( const SubsetEntry& rSubsetEntry )
+ {
+ // TODO(F1): This removes too much from non-contiguous subsets
+ mnMinSubsetActionIndex = ::std::min(
+ mnMinSubsetActionIndex,
+ rSubsetEntry.mnStartActionIndex );
+ mnMaxSubsetActionIndex = ::std::max(
+ mnMaxSubsetActionIndex,
+ rSubsetEntry.mnEndActionIndex );
+ }
+
+ void DrawShapeSubsetting::updateSubsets()
+ {
+ maCurrentSubsets.clear();
+
+ if( !maSubsetShapes.empty() )
+ {
+ if( maSubset.isEmpty() )
+ {
+ // non-subsetted node, with some child subsets
+ // that subtract from it
+ maCurrentSubsets.push_back( DocTreeNode( 0,
+ mnMinSubsetActionIndex,
+ DocTreeNode::NODETYPE_INVALID ) );
+ maCurrentSubsets.push_back( DocTreeNode( mnMaxSubsetActionIndex,
+ maActionClassVector.size(),
+ DocTreeNode::NODETYPE_INVALID ) );
+ }
+ else
+ {
+ // subsetted node, from which some further child
+ // subsets subtract content
+ maCurrentSubsets.push_back( DocTreeNode( maSubset.getStartIndex(),
+ mnMinSubsetActionIndex,
+ DocTreeNode::NODETYPE_INVALID ) );
+ maCurrentSubsets.push_back( DocTreeNode( mnMaxSubsetActionIndex,
+ maSubset.getEndIndex(),
+ DocTreeNode::NODETYPE_INVALID ) );
+ }
+ }
+ else
+ {
+ // no further child subsets, simply add our subset (if any)
+ if( !maSubset.isEmpty() )
+ {
+ // subsetted node, without any subset children
+ maCurrentSubsets.push_back( maSubset );
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ //
+ // Public methods
+ //
+ //////////////////////////////////////////////////////////////////////
+
+ DrawShapeSubsetting::DrawShapeSubsetting() :
+ maActionClassVector(),
+ mpMtf(),
+ maSubset(),
+ maSubsetShapes(),
+ mnMinSubsetActionIndex( SAL_MAX_INT32 ),
+ mnMaxSubsetActionIndex(0),
+ maCurrentSubsets(),
+ mbNodeTreeInitialized( false )
+ {
+ }
+
+ DrawShapeSubsetting::DrawShapeSubsetting( const GDIMetaFileSharedPtr& rMtf ) :
+ maActionClassVector(),
+ mpMtf( rMtf ),
+ maSubset(),
+ maSubsetShapes(),
+ mnMinSubsetActionIndex( SAL_MAX_INT32 ),
+ mnMaxSubsetActionIndex(0),
+ maCurrentSubsets(),
+ mbNodeTreeInitialized( false )
+ {
+ ENSURE_OR_THROW( mpMtf,
+ "DrawShapeSubsetting::DrawShapeSubsetting(): Invalid metafile" );
+
+ initCurrentSubsets();
+ }
+
+ DrawShapeSubsetting::DrawShapeSubsetting( const DocTreeNode& rShapeSubset,
+ const GDIMetaFileSharedPtr& rMtf ) :
+ maActionClassVector(),
+ mpMtf( rMtf ),
+ maSubset( rShapeSubset ),
+ maSubsetShapes(),
+ mnMinSubsetActionIndex( SAL_MAX_INT32 ),
+ mnMaxSubsetActionIndex(0),
+ maCurrentSubsets(),
+ mbNodeTreeInitialized( false )
+ {
+ ENSURE_OR_THROW( mpMtf,
+ "DrawShapeSubsetting::DrawShapeSubsetting(): Invalid metafile" );
+
+ initCurrentSubsets();
+ }
+
+ void DrawShapeSubsetting::reset()
+ {
+ maActionClassVector.clear();
+ mpMtf.reset();
+ maSubset.reset();
+ maSubsetShapes.clear();
+ mnMinSubsetActionIndex = SAL_MAX_INT32;
+ mnMaxSubsetActionIndex = 0;
+ maCurrentSubsets.clear();
+ mbNodeTreeInitialized = false;
+ }
+
+ void DrawShapeSubsetting::reset( const ::boost::shared_ptr< GDIMetaFile >& rMtf )
+ {
+ reset();
+ mpMtf = rMtf;
+
+ initCurrentSubsets();
+ }
+
+ void DrawShapeSubsetting::reset( const DocTreeNode& rShapeSubset,
+ const ::boost::shared_ptr< GDIMetaFile >& rMtf )
+ {
+ reset();
+ mpMtf = rMtf;
+ maSubset = rShapeSubset;
+
+ initCurrentSubsets();
+ }
+
+ void DrawShapeSubsetting::initCurrentSubsets()
+ {
+ // only add subset to vector, if it's not empty - that's
+ // because the vector's content is later literally used
+ // for e.g. painting.
+ if( !maSubset.isEmpty() )
+ maCurrentSubsets.push_back( maSubset );
+ }
+
+ DocTreeNode DrawShapeSubsetting::getSubsetNode() const
+ {
+ return maSubset;
+ }
+
+ bool DrawShapeSubsetting::hasSubsetShapes() const
+ {
+ return !maSubsetShapes.empty();
+ }
+
+ AttributableShapeSharedPtr DrawShapeSubsetting::getSubsetShape( const DocTreeNode& rTreeNode ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShapeSubsetting::getSubsetShape()" );
+
+ // subset shape already created for this DocTreeNode?
+ SubsetEntry aEntry;
+
+ aEntry.mnStartActionIndex = rTreeNode.getStartIndex();
+ aEntry.mnEndActionIndex = rTreeNode.getEndIndex();
+
+ ShapeSet::const_iterator aIter;
+ if( (aIter=maSubsetShapes.find( aEntry )) != maSubsetShapes.end() )
+ {
+ // already created, return found entry
+ return aIter->mpShape;
+ }
+
+ return AttributableShapeSharedPtr();
+ }
+
+ void DrawShapeSubsetting::addSubsetShape( const AttributableShapeSharedPtr& rShape )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShapeSubsetting::addSubsetShape()" );
+
+ // subset shape already created for this DocTreeNode?
+ SubsetEntry aEntry;
+ const DocTreeNode& rEffectiveSubset( rShape->getSubsetNode() );
+
+ aEntry.mnStartActionIndex = rEffectiveSubset.getStartIndex();
+ aEntry.mnEndActionIndex = rEffectiveSubset.getEndIndex();
+
+ ShapeSet::const_iterator aIter;
+ if( (aIter=maSubsetShapes.find( aEntry )) != maSubsetShapes.end() )
+ {
+ // already created, increment use count and return
+
+ // safe cast, since set order does not depend on
+ // mnSubsetQueriedCount
+ const_cast<SubsetEntry&>(*aIter).mnSubsetQueriedCount++;
+ }
+ else
+ {
+ // not yet created, init entry
+ aEntry.mnSubsetQueriedCount = 1;
+ aEntry.mpShape = rShape;
+
+ maSubsetShapes.insert( aEntry );
+
+ // update cached subset borders
+ updateSubsetBounds( aEntry );
+ updateSubsets();
+ }
+ }
+
+ bool DrawShapeSubsetting::revokeSubsetShape( const AttributableShapeSharedPtr& rShape )
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShapeSubsetting::revokeSubsetShape()" );
+
+ // lookup subset shape
+ SubsetEntry aEntry;
+ const DocTreeNode& rEffectiveSubset( rShape->getSubsetNode() );
+
+ aEntry.mnStartActionIndex = rEffectiveSubset.getStartIndex();
+ aEntry.mnEndActionIndex = rEffectiveSubset.getEndIndex();
+
+ ShapeSet::iterator aIter;
+ if( (aIter=maSubsetShapes.find( aEntry )) == maSubsetShapes.end() )
+ return false; // not found, subset was never queried
+
+ // last client of the subset revoking?
+ if( aIter->mnSubsetQueriedCount > 1 )
+ {
+ // no, still clients out there. Just decrement use count
+ // safe cast, since order does not depend on mnSubsetQueriedCount
+ const_cast<SubsetEntry&>(*aIter).mnSubsetQueriedCount--;
+
+ VERBOSE_TRACE( "Subset summary: shape 0x%X, %d open subsets, revoked subset has refcount %d",
+ this,
+ maSubsetShapes.size(),
+ aIter->mnSubsetQueriedCount );
+
+ return false; // not the last client
+ }
+
+ VERBOSE_TRACE( "Subset summary: shape 0x%X, %d open subsets, cleared subset has range [%d,%d]",
+ this,
+ maSubsetShapes.size(),
+ aEntry.mnStartActionIndex,
+ aEntry.mnEndActionIndex );
+
+ // yes, remove from set
+ maSubsetShapes.erase( aIter );
+
+
+ // update currently active subset for _our_ shape (the
+ // part of this shape that is visible, i.e. not displayed
+ // in subset shapes)
+ // ======================================================
+
+ // init bounds
+ mnMinSubsetActionIndex = SAL_MAX_INT32;
+ mnMaxSubsetActionIndex = 0;
+
+ // TODO(P2): This is quite expensive, when
+ // after every subset effect end, we have to scan
+ // the whole shape set
+
+ // determine new subset range
+ ::std::for_each( maSubsetShapes.begin(),
+ maSubsetShapes.end(),
+ ::boost::bind(&DrawShapeSubsetting::updateSubsetBounds,
+ this,
+ _1 ) );
+
+ updateSubsets();
+
+ return true;
+ }
+
+ namespace
+ {
+ /** Iterate over all action classification entries in the
+ given range, pass each element range found to the
+ given functor.
+
+ This method extracts, for each of the different action
+ classifications, the count and the ranges for each of
+ them, and calls the provided functor with that
+ information.
+
+ @tpl FunctorT
+ This is the functor's operator() calling signature,
+ with eCurrElemClassification denoting the current
+ classification type the functor is called for,
+ nCurrElemCount the running total of elements visited
+ for the given class (starting from 0), and
+ rCurrElemBegin/rCurrElemEnd the range of the current
+ element (i.e. the iterators from the start to the end
+ of this element).
+ <pre>
+ bool operator()( IndexClassificator eCurrElemClassification
+ sal_Int32 nCurrElemCount,
+ const IndexClassificatorVector::const_iterator& rCurrElemBegin,
+ const IndexClassificatorVector::const_iterator& rCurrElemEnd );
+ </pre>
+ If the functor returns false, iteration over the
+ shapes is immediately stopped.
+
+ @param io_pFunctor
+ This functor is called for every shape found.
+
+ @param rBegin
+ Start of range to iterate over
+
+ @param rEnd
+ End of range to iterate over
+
+ @return the number of shapes found in the metafile
+ */
+ template< typename FunctorT > void iterateActionClassifications(
+ FunctorT& io_rFunctor,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rBegin,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rEnd )
+ {
+ sal_Int32 nCurrShapeCount( 0 );
+ sal_Int32 nCurrParaCount( 0 );
+ sal_Int32 nCurrLineCount( 0 );
+ sal_Int32 nCurrSentenceCount( 0 );
+ sal_Int32 nCurrWordCount( 0 );
+ sal_Int32 nCurrCharCount( 0 );
+
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastShapeStart(rBegin);
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastParaStart(rBegin);
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastLineStart(rBegin);
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastSentenceStart(rBegin);
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastWordStart(rBegin);
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastCharStart(rBegin);
+
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aNext;
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator aCurr( rBegin );
+ while( aCurr != rEnd )
+ {
+ // aNext will hold an iterator to the next element
+ // (or the past-the-end iterator, if aCurr
+ // references the last element). Used to pass a
+ // valid half-open range to the functors.
+ aNext = aCurr;
+ ++aNext;
+
+ switch( *aCurr )
+ {
+ default:
+ ENSURE_OR_THROW( false,
+ "Unexpected type in iterateDocShapes()" );
+ case DrawShapeSubsetting::CLASS_NOOP:
+ // ignore NOOP actions
+ break;
+
+ case DrawShapeSubsetting::CLASS_SHAPE_START:
+ // regardless of ending action
+ // classifications before: a new shape
+ // always also starts contained elements
+ // anew
+ aLastShapeStart =
+ aLastParaStart =
+ aLastLineStart =
+ aLastSentenceStart =
+ aLastWordStart =
+ aLastCharStart = aCurr;
+ break;
+
+ case DrawShapeSubsetting::CLASS_SHAPE_END:
+ if( !io_rFunctor( DrawShapeSubsetting::CLASS_SHAPE_END,
+ nCurrShapeCount,
+ aLastShapeStart,
+ aNext ) )
+ {
+ return;
+ }
+
+ ++nCurrShapeCount;
+ // FALLTHROUGH intended: shape end also
+ // ends lines
+ case DrawShapeSubsetting::CLASS_PARAGRAPH_END:
+ if( !io_rFunctor( DrawShapeSubsetting::CLASS_PARAGRAPH_END,
+ nCurrParaCount,
+ aLastParaStart,
+ aNext ) )
+ {
+ return;
+ }
+
+ ++nCurrParaCount;
+ aLastParaStart = aNext;
+ // FALLTHROUGH intended: para end also
+ // ends line
+ case DrawShapeSubsetting::CLASS_LINE_END:
+ if( !io_rFunctor( DrawShapeSubsetting::CLASS_LINE_END,
+ nCurrLineCount,
+ aLastLineStart,
+ aNext ) )
+ {
+ return;
+ }
+
+ ++nCurrLineCount;
+ aLastLineStart = aNext;
+
+ if( *aCurr == DrawShapeSubsetting::CLASS_LINE_END )
+ {
+ // DON'T fall through here, as a line
+ // does NOT end neither a sentence,
+ // nor a word. OTOH, all parent
+ // structures (paragraph and shape),
+ // which itself fall through to this
+ // code, DO end word, sentence and
+ // character cell.
+
+ // TODO(F1): Maybe a line should end a
+ // character cell, OTOH?
+ break;
+ }
+ // FALLTHROUGH intended
+ case DrawShapeSubsetting::CLASS_SENTENCE_END:
+ if( !io_rFunctor( DrawShapeSubsetting::CLASS_SENTENCE_END,
+ nCurrSentenceCount,
+ aLastSentenceStart,
+ aNext ) )
+ {
+ return;
+ }
+
+ ++nCurrSentenceCount;
+ aLastSentenceStart = aNext;
+ // FALLTHROUGH intended
+ case DrawShapeSubsetting::CLASS_WORD_END:
+ if( !io_rFunctor( DrawShapeSubsetting::CLASS_WORD_END,
+ nCurrWordCount,
+ aLastWordStart,
+ aNext ) )
+ {
+ return;
+ }
+
+ ++nCurrWordCount;
+ aLastWordStart = aNext;
+ // FALLTHROUGH intended
+ case DrawShapeSubsetting::CLASS_CHARACTER_CELL_END:
+ if( !io_rFunctor( DrawShapeSubsetting::CLASS_CHARACTER_CELL_END,
+ nCurrCharCount,
+ aLastCharStart,
+ aNext ) )
+ {
+ return;
+ }
+
+ ++nCurrCharCount;
+ aLastCharStart = aNext;
+ break;
+ }
+
+ aCurr = aNext;
+ }
+ }
+
+ DrawShapeSubsetting::IndexClassificator mapDocTreeNode( DocTreeNode::NodeType eNodeType )
+ {
+ switch( eNodeType )
+ {
+ case DocTreeNode::NODETYPE_INVALID:
+ // FALLTHROUGH intended
+ default:
+ OSL_ENSURE(false,
+ "DrawShapeSubsetting::mapDocTreeNode(): unexpected node type");
+ return DrawShapeSubsetting::CLASS_NOOP;
+
+ case DocTreeNode::NODETYPE_LOGICAL_SHAPE:
+ // FALLTHROUGH intended
+ case DocTreeNode::NODETYPE_FORMATTING_SHAPE:
+ return DrawShapeSubsetting::CLASS_SHAPE_END;
+
+ case DocTreeNode::NODETYPE_FORMATTING_LINE:
+ return DrawShapeSubsetting::CLASS_LINE_END;
+
+ case DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH:
+ return DrawShapeSubsetting::CLASS_PARAGRAPH_END;
+
+ case DocTreeNode::NODETYPE_LOGICAL_SENTENCE:
+ return DrawShapeSubsetting::CLASS_SENTENCE_END;
+
+ case DocTreeNode::NODETYPE_LOGICAL_WORD:
+ return DrawShapeSubsetting::CLASS_WORD_END;
+
+ case DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL:
+ return DrawShapeSubsetting::CLASS_CHARACTER_CELL_END;
+ };
+ }
+
+ /// Counts number of class occurences
+ class CountClassFunctor
+ {
+ public:
+ CountClassFunctor( DrawShapeSubsetting::IndexClassificator eClass ) :
+ meClass( eClass ),
+ mnCurrCount(0)
+ {
+ }
+
+ bool operator()( DrawShapeSubsetting::IndexClassificator eCurrElemClassification,
+ sal_Int32 /*nCurrElemCount*/,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& /*rCurrElemBegin*/,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& /*rCurrElemEnd*/ )
+ {
+ if( eCurrElemClassification == meClass )
+ ++mnCurrCount;
+
+ return true; // never stop, count all occurences
+ }
+
+ sal_Int32 getCount() const
+ {
+ return mnCurrCount;
+ }
+
+ private:
+ DrawShapeSubsetting::IndexClassificator meClass;
+ sal_Int32 mnCurrCount;
+ };
+ }
+
+ sal_Int32 DrawShapeSubsetting::implGetNumberOfTreeNodes( const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rBegin,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rEnd,
+ DocTreeNode::NodeType eNodeType ) const
+ {
+ const IndexClassificator eRequestedClass(
+ mapDocTreeNode( eNodeType ) );
+
+ // create a counting functor for the requested class of
+ // actions
+ CountClassFunctor aFunctor( eRequestedClass );
+
+ // count all occurences in the given range
+ iterateActionClassifications( aFunctor, rBegin, rEnd );
+
+ return aFunctor.getCount();
+ }
+
+ sal_Int32 DrawShapeSubsetting::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const
+ {
+ ensureInitializedNodeTree();
+
+ return implGetNumberOfTreeNodes( maActionClassVector.begin(),
+ maActionClassVector.end(),
+ eNodeType );
+ }
+
+ namespace
+ {
+ /** This functor finds the nth occurrence of a given
+ action class.
+
+ The operator() compares the given index value with the
+ requested index, as given on the functor's
+ constructor. Then, the operator() returns false,
+ denoting that the requested action is found.
+ */
+ class FindNthElementFunctor
+ {
+ public:
+ FindNthElementFunctor( sal_Int32 nNodeIndex,
+ DrawShapeSubsetting::IndexClassificator eClass ) :
+ mnNodeIndex( nNodeIndex ),
+ meClass( eClass )
+ {
+ }
+
+ bool operator()( DrawShapeSubsetting::IndexClassificator eCurrElemClassification,
+ sal_Int32 nCurrElemCount,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rCurrElemBegin,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rCurrElemEnd )
+ {
+ if( eCurrElemClassification == meClass &&
+ nCurrElemCount == mnNodeIndex )
+ {
+ maLastBegin = rCurrElemBegin;
+ maLastEnd = rCurrElemEnd;
+
+ return false; // abort iteration, we've
+ // already found what we've been
+ // looking for
+ }
+
+ return true; // keep on truckin'
+ }
+
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator getBeginElement() const
+ {
+ return maLastBegin;
+ }
+
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator getEndElement() const
+ {
+ return maLastEnd;
+ }
+
+ private:
+ sal_Int32 mnNodeIndex;
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator maLastBegin;
+ DrawShapeSubsetting::IndexClassificatorVector::const_iterator maLastEnd;
+ DrawShapeSubsetting::IndexClassificator meClass;
+ };
+
+ DocTreeNode makeTreeNode( const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rBegin,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rStart,
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rEnd,
+ DocTreeNode::NodeType eNodeType )
+ {
+ return DocTreeNode( ::std::distance(rBegin,
+ rStart),
+ ::std::distance(rBegin,
+ rEnd),
+ eNodeType );
+ }
+ }
+
+ DocTreeNode DrawShapeSubsetting::implGetTreeNode( const IndexClassificatorVector::const_iterator& rBegin,
+ const IndexClassificatorVector::const_iterator& rEnd,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const
+ {
+ const IndexClassificator eRequestedClass(
+ mapDocTreeNode( eNodeType ) );
+
+ // create a nth element functor for the requested class of
+ // actions, and nNodeIndex as the target index
+ FindNthElementFunctor aFunctor( nNodeIndex,
+ eRequestedClass );
+
+ // find given index in the given range
+ iterateActionClassifications( aFunctor, rBegin, rEnd );
+
+ return makeTreeNode( maActionClassVector.begin(),
+ aFunctor.getBeginElement(),
+ aFunctor.getEndElement(),
+ eNodeType );
+ }
+
+ DocTreeNode DrawShapeSubsetting::getTreeNode( sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const
+ {
+ ensureInitializedNodeTree();
+
+ return implGetTreeNode( maActionClassVector.begin(),
+ maActionClassVector.end(),
+ nNodeIndex,
+ eNodeType );
+ }
+
+ sal_Int32 DrawShapeSubsetting::getNumberOfSubsetTreeNodes( const DocTreeNode& rParentNode,
+ DocTreeNode::NodeType eNodeType ) const
+ {
+ ensureInitializedNodeTree();
+
+ // convert from vector indices to vector iterators
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aBegin( maActionClassVector.begin() );
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentBegin( aBegin + rParentNode.getStartIndex() );
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentEnd( aBegin + rParentNode.getEndIndex() );
+
+ return implGetNumberOfTreeNodes( aParentBegin,
+ aParentEnd,
+ eNodeType );
+ }
+
+ DocTreeNode DrawShapeSubsetting::getSubsetTreeNode( const DocTreeNode& rParentNode,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const
+ {
+ ensureInitializedNodeTree();
+
+ // convert from vector indices to vector iterators
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aBegin( maActionClassVector.begin() );
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentBegin( aBegin + rParentNode.getStartIndex() );
+ const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentEnd( aBegin + rParentNode.getEndIndex() );
+
+ return implGetTreeNode( aParentBegin,
+ aParentEnd,
+ nNodeIndex,
+ eNodeType );
+ }
+
+ const VectorOfDocTreeNodes& DrawShapeSubsetting::getActiveSubsets() const
+ {
+ return maCurrentSubsets;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawshapesubsetting.hxx b/slideshow/source/engine/shapes/drawshapesubsetting.hxx
new file mode 100644
index 000000000000..0177907c1f3d
--- /dev/null
+++ b/slideshow/source/engine/shapes/drawshapesubsetting.hxx
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DRAWSHAPESUBSETTING_HXX
+#define INCLUDED_SLIDESHOW_DRAWSHAPESUBSETTING_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#include "doctreenode.hxx"
+#include "attributableshape.hxx"
+
+
+class GDIMetaFile;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class encapsulates the subsetting aspects of a
+ DrawShape.
+ */
+ class DrawShapeSubsetting : private boost::noncopyable
+ {
+ public:
+ /** Create empty shape subset handling.
+
+ This method creates a subset handler which contains no
+ subset information. All methods will return default
+ values.
+
+ @param rMtf
+ Metafile to retrieve subset info from (must have been
+ generated with verbose text comments switched on).
+ */
+ DrawShapeSubsetting();
+
+ /** Create new shape subset handling.
+
+ This method creates a subset handler which initially
+ displays the whole shape.
+
+ @param rMtf
+ Metafile to retrieve subset info from (must have been
+ generated with verbose text comments switched on).
+ */
+ explicit DrawShapeSubsetting( const ::boost::shared_ptr< GDIMetaFile >& rMtf );
+
+ /** Create new shape subset handling.
+
+ @param rShapeSubset
+ The subset this object represents (can be empty, then
+ denoting 'represents a whole shape')
+
+ @param rMtf
+ Metafile to retrieve subset info from (must have been
+ generated with verbose text comments switched on).
+ */
+ DrawShapeSubsetting( const DocTreeNode& rShapeSubset,
+ const ::boost::shared_ptr< GDIMetaFile >& rMtf );
+
+ /** Reset metafile.
+
+ Use this method to completely reset the
+ ShapeSubsetting, with a new metafile. Note that any
+ information previously set will be lost, including
+ added subset shapes!
+
+ @param rMtf
+ Metafile to retrieve subset info from (must have been
+ generated with verbose text comments switched on).
+ */
+ void reset( const ::boost::shared_ptr< GDIMetaFile >& rMtf );
+
+ /** Reset metafile and subset.
+
+ Use this method to completely reset the
+ ShapeSubsetting, with a new metafile and subset
+ range. Note that any information previously set will
+ be lost, including added subset shapes!
+
+ @param rShapeSubset
+ The subset this object represents (can be empty, then
+ denoting 'represents a whole shape')
+
+ @param rMtf
+ Metafile to retrieve subset info from (must have been
+ generated with verbose text comments switched on).
+ */
+ void reset( const DocTreeNode& rShapeSubset,
+ const ::boost::shared_ptr< GDIMetaFile >& rMtf );
+
+
+ // Shape subsetting methods
+ // ========================================================
+
+ /// Return subset node for this shape
+ DocTreeNode getSubsetNode () const;
+
+ /// Return true, if any child subset shapes exist
+ bool hasSubsetShapes () const;
+
+ /// Get subset shape for given node, if any
+ AttributableShapeSharedPtr getSubsetShape ( const DocTreeNode& rTreeNode ) const;
+
+ /// Add child subset shape (or increase use count, if already existent)
+ void addSubsetShape ( const AttributableShapeSharedPtr& rShape );
+
+ /** Revoke subset shape
+
+ This method revokes a subset shape, decrementing the
+ use count for this subset by one. If the use count
+ reaches zero (i.e. when the number of addSubsetShape()
+ matches the number of revokeSubsetShape() calls for
+ the same subset), the subset entry is removed from the
+ internal list, and subsequent getSubsetShape() calls
+ will return the empty pointer for this subset.
+
+ @return true, if the subset shape was physically
+ removed from the list (false is returned, when nothing
+ was removed, either because only the use count was
+ decremented, or there was no such subset found, in the
+ first place).
+ */
+ bool revokeSubsetShape ( const AttributableShapeSharedPtr& rShape );
+
+
+ // Doc tree methods
+ // ========================================================
+
+ /// Return overall number of nodes for given type
+ sal_Int32 getNumberOfTreeNodes ( DocTreeNode::NodeType eNodeType ) const;
+
+ /// Return tree node of given index and given type
+ DocTreeNode getTreeNode ( sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const;
+
+ /// Return number of nodes of given type, below parent node
+ sal_Int32 getNumberOfSubsetTreeNodes ( const DocTreeNode& rParentNode,
+ DocTreeNode::NodeType eNodeType ) const;
+
+ /// Return tree node of given index and given type, relative to parent node
+ DocTreeNode getSubsetTreeNode ( const DocTreeNode& rParentNode,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const;
+
+ // Helper
+ // ========================================================
+
+ /** Return a vector of currently active subsets.
+
+ Needed when rendering a shape, this method provides a
+ vector of subsets currently visible (the range as
+ returned by getEffectiveSubset(), minus the parts that
+ are currently hidden, because displayed by child
+ shapes).
+ */
+ const VectorOfDocTreeNodes& getActiveSubsets() const;
+
+ /** This enum classifies each action index in the
+ metafile.
+
+ Of interest are, of course, the places where
+ structural shape and/or text elements end. The
+ remainder of the action gets classified as 'noop'
+ */
+ enum IndexClassificator
+ {
+ CLASS_NOOP,
+ CLASS_SHAPE_START,
+ CLASS_SHAPE_END,
+
+ CLASS_LINE_END,
+ CLASS_PARAGRAPH_END,
+ CLASS_SENTENCE_END,
+ CLASS_WORD_END,
+ CLASS_CHARACTER_CELL_END
+ };
+
+ typedef ::std::vector< IndexClassificator > IndexClassificatorVector;
+
+ private:
+ /** Entry for subset shape
+
+ This struct contains data for every subset shape
+ generated. Note that for a given start/end action
+ index combination, only one subset instance is
+ generated (and reused for subsequent queries).
+ */
+ struct SubsetEntry
+ {
+ AttributableShapeSharedPtr mpShape;
+ sal_Int32 mnStartActionIndex;
+ sal_Int32 mnEndActionIndex;
+
+ /// Number of times this subset was queried, and not yet revoked
+ int mnSubsetQueriedCount;
+
+ sal_Int32 getHashValue() const
+ {
+ // TODO(Q3): That's a hack. We assume that start
+ // index will always be less than 65535 (if this
+ // assumption is violated, hash map performance
+ // will degrade severely)
+ return mnStartActionIndex*SAL_MAX_INT16 + mnEndActionIndex;
+ }
+
+ /// The shape set is ordered according to this method
+ bool operator<(const SubsetEntry& rOther) const
+ {
+ return getHashValue() < rOther.getHashValue();
+ }
+
+ };
+
+ typedef ::std::set< SubsetEntry > ShapeSet;
+
+ void ensureInitializedNodeTree() const;
+ void updateSubsetBounds( const SubsetEntry& rSubsetEntry );
+ void updateSubsets();
+ void initCurrentSubsets();
+ void reset();
+
+ sal_Int32 implGetNumberOfTreeNodes( const IndexClassificatorVector::const_iterator& rBegin,
+ const IndexClassificatorVector::const_iterator& rEnd,
+ DocTreeNode::NodeType eNodeType ) const;
+ DocTreeNode implGetTreeNode( const IndexClassificatorVector::const_iterator& rBegin,
+ const IndexClassificatorVector::const_iterator& rEnd,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const;
+
+ mutable IndexClassificatorVector maActionClassVector;
+
+ /// Metafile to retrieve subset info from
+ ::boost::shared_ptr< GDIMetaFile > mpMtf;
+
+ /// Subset of the metafile represented by this object
+ DocTreeNode maSubset;
+
+ /// the list of subset shapes spawned from this one.
+ ShapeSet maSubsetShapes;
+
+ /// caches minimal subset index from maSubsetShapes
+ sal_Int32 mnMinSubsetActionIndex;
+
+ /// caches maximal subset index from maSubsetShapes
+ sal_Int32 mnMaxSubsetActionIndex;
+
+ /** Current number of subsets to render (calculated from
+ maSubset and mnMin/MaxSubsetActionIndex).
+
+ Note that this is generally _not_ equivalent to
+ maSubset, as it excludes all active subset children!
+ */
+ mutable VectorOfDocTreeNodes maCurrentSubsets;
+
+ /// Whether the shape's doc tree has been initialized successfully, or not
+ mutable bool mbNodeTreeInitialized;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_DRAWSHAPESUBSETTING_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/externalshapebase.cxx b/slideshow/source/engine/shapes/externalshapebase.cxx
new file mode 100644
index 000000000000..2d70a5bbad8d
--- /dev/null
+++ b/slideshow/source/engine/shapes/externalshapebase.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include "externalshapebase.hxx"
+#include "eventmultiplexer.hxx"
+#include "vieweventhandler.hxx"
+#include "intrinsicanimationeventhandler.hxx"
+#include "tools.hxx"
+
+#include <boost/noncopyable.hpp>
+
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class ExternalShapeBase::ExternalShapeBaseListener : public ViewEventHandler,
+ public IntrinsicAnimationEventHandler,
+ private boost::noncopyable
+ {
+ public:
+ explicit ExternalShapeBaseListener( ExternalShapeBase& rBase ) :
+ mrBase( rBase )
+ {}
+
+
+ private:
+ // ViewEventHandler
+ // -------------------------------------------------
+
+ virtual void viewAdded( const UnoViewSharedPtr& ) {}
+ virtual void viewRemoved( const UnoViewSharedPtr& ) {}
+ virtual void viewChanged( const UnoViewSharedPtr& rView )
+ {
+ mrBase.implViewChanged(rView);
+ }
+ virtual void viewsChanged()
+ {
+ mrBase.implViewsChanged();
+ }
+
+
+ // IntrinsicAnimationEventHandler
+ // -------------------------------------------------
+
+ virtual bool enableAnimations()
+ {
+ return mrBase.implStartIntrinsicAnimation();
+ }
+ virtual bool disableAnimations()
+ {
+ return mrBase.implEndIntrinsicAnimation();
+ }
+
+ ExternalShapeBase& mrBase;
+ };
+
+
+ ExternalShapeBase::ExternalShapeBase( const uno::Reference< drawing::XShape >& xShape,
+ double nPrio,
+ const SlideShowContext& rContext ) :
+ mxComponentContext( rContext.mxComponentContext ),
+ mxShape( xShape ),
+ mpListener( new ExternalShapeBaseListener(*this) ),
+ mpShapeManager( rContext.mpSubsettableShapeManager ),
+ mrEventMultiplexer( rContext.mrEventMultiplexer ),
+ mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
+ maBounds( getAPIShapeBounds( xShape ) )
+ {
+ ENSURE_OR_THROW( mxShape.is(), "ExternalShapeBase::ExternalShapeBase(): Invalid XShape" );
+
+ mpShapeManager->addIntrinsicAnimationHandler( mpListener );
+ mrEventMultiplexer.addViewHandler( mpListener );
+ }
+
+ // ---------------------------------------------------------------------
+
+ ExternalShapeBase::~ExternalShapeBase()
+ {
+ try
+ {
+ mrEventMultiplexer.removeViewHandler( mpListener );
+ mpShapeManager->removeIntrinsicAnimationHandler( mpListener );
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ uno::Reference< drawing::XShape > ExternalShapeBase::getXShape() const
+ {
+ return mxShape;
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ExternalShapeBase::play()
+ {
+ implStartIntrinsicAnimation();
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ExternalShapeBase::stop()
+ {
+ implEndIntrinsicAnimation();
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ExternalShapeBase::pause()
+ {
+ implPauseIntrinsicAnimation();
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ExternalShapeBase::isPlaying() const
+ {
+ return implIsIntrinsicAnimationPlaying();
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ExternalShapeBase::setMediaTime(double fTime)
+ {
+ implSetIntrinsicAnimationTime(fTime);
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ExternalShapeBase::update() const
+ {
+ return render();
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ExternalShapeBase::render() const
+ {
+ if( maBounds.getRange().equalZero() )
+ {
+ // zero-sized shapes are effectively invisible,
+ // thus, we save us the rendering...
+ return true;
+ }
+
+ return implRender( maBounds );
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ExternalShapeBase::isContentChanged() const
+ {
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ ::basegfx::B2DRectangle ExternalShapeBase::getBounds() const
+ {
+ return maBounds;
+ }
+
+ // ---------------------------------------------------------------------
+
+ ::basegfx::B2DRectangle ExternalShapeBase::getDomBounds() const
+ {
+ return maBounds;
+ }
+
+ // ---------------------------------------------------------------------
+
+ ::basegfx::B2DRectangle ExternalShapeBase::getUpdateArea() const
+ {
+ return maBounds;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ExternalShapeBase::isVisible() const
+ {
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ double ExternalShapeBase::getPriority() const
+ {
+ return mnPriority;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ExternalShapeBase::isBackgroundDetached() const
+ {
+ // external shapes always have their own window/surface
+ return true;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/externalshapebase.hxx b/slideshow/source/engine/shapes/externalshapebase.hxx
new file mode 100644
index 000000000000..8e415fcc394d
--- /dev/null
+++ b/slideshow/source/engine/shapes/externalshapebase.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EXTERNALSHAPEBASE_HXX
+#define INCLUDED_SLIDESHOW_EXTERNALSHAPEBASE_HXX
+
+#include <vector>
+
+#include "externalmediashape.hxx"
+#include "unoview.hxx"
+#include "subsettableshapemanager.hxx"
+#include "slideshowexceptions.hxx"
+#include "slideshowcontext.hxx"
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Base class for shapes rendered by external engines.
+
+ Used as the common base for e.g. MediaShape or
+ AppletShape, all of which are rendered by external
+ components (and all employ distinct windows).
+
+ Please note that this base class indeed assumes the shape
+ does not interfere with the internal shapes in any way
+ (including mutual overdraw). It therefore reports yes for
+ the isBackgroundDetached() question.
+ */
+ class ExternalShapeBase : public ExternalMediaShape
+ {
+ public:
+ /** Create a shape for the given XShape for an external shape
+
+ @param xShape
+ The XShape to represent.
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+ */
+ ExternalShapeBase( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ double nPrio,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+ virtual ~ExternalShapeBase();
+
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > getXShape() const;
+
+ // animation methods
+ //------------------------------------------------------------------
+
+ virtual void play();
+ virtual void stop();
+ virtual void pause();
+ virtual bool isPlaying() const;
+ virtual void setMediaTime(double);
+
+ // render methods
+ //------------------------------------------------------------------
+
+ virtual bool update() const;
+ virtual bool render() const;
+ virtual bool isContentChanged() const;
+
+
+ // Shape attributes
+ //------------------------------------------------------------------
+
+ virtual ::basegfx::B2DRectangle getBounds() const;
+ virtual ::basegfx::B2DRectangle getDomBounds() const;
+ virtual ::basegfx::B2DRectangle getUpdateArea() const;
+ virtual bool isVisible() const;
+ virtual double getPriority() const;
+ virtual bool isBackgroundDetached() const;
+
+ protected:
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext> mxComponentContext;
+
+ private:
+ class ExternalShapeBaseListener; friend class ExternalShapeBaseListener;
+
+ /// override in derived class to render preview
+ virtual bool implRender( const ::basegfx::B2DRange& rCurrBounds ) const = 0;
+
+ /// override in derived class to resize
+ virtual void implViewChanged( const UnoViewSharedPtr& rView ) = 0;
+ /// override in derived class to resize
+ virtual void implViewsChanged() = 0;
+
+ /// override in derived class to start external viewer
+ virtual bool implStartIntrinsicAnimation() = 0;
+ /// override in derived class to stop external viewer
+ virtual bool implEndIntrinsicAnimation() = 0;
+ /// override in derived class to pause external viewer
+ virtual bool implPauseIntrinsicAnimation() = 0;
+ /// override in derived class to return status of animation
+ virtual bool implIsIntrinsicAnimationPlaying() const = 0;
+ /// override in derived class to set media time
+ virtual void implSetIntrinsicAnimationTime(double) = 0;
+
+
+ /// The associated XShape
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > mxShape;
+
+ boost::shared_ptr<ExternalShapeBaseListener> mpListener;
+
+ SubsettableShapeManagerSharedPtr mpShapeManager;
+ EventMultiplexer& mrEventMultiplexer;
+
+ // The attributes of this Shape
+ const double mnPriority;
+ ::basegfx::B2DRectangle maBounds;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_EXTERNALSHAPEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/gdimtftools.cxx b/slideshow/source/engine/shapes/gdimtftools.cxx
new file mode 100644
index 000000000000..014433d04e12
--- /dev/null
+++ b/slideshow/source/engine/shapes/gdimtftools.cxx
@@ -0,0 +1,551 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <gdimtftools.hxx>
+
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/graphic/XGraphicRenderer.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase1.hxx>
+
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+#include <tools/stream.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/animate.hxx>
+#include <vcl/graph.hxx>
+
+#include <unotools/streamwrap.hxx>
+
+#include "tools.hxx"
+
+using namespace ::com::sun::star;
+
+
+// free support functions
+// ======================
+
+namespace slideshow
+{
+namespace internal
+{
+// TODO(E2): Detect the case when svx/drawing layer is not
+// in-process, or even not on the same machine, and
+// fallback to metafile streaming!
+
+// For fixing #i48102#, have to be a _lot_ more selective
+// on which metafiles to convert to bitmaps. The problem
+// here is that we _always_ get the shape content as a
+// metafile, even if we have a bitmap graphic shape. Thus,
+// calling GetBitmapEx on such a Graphic (see below) will
+// result in one poorly scaled bitmap into another,
+// somewhat arbitrarily sized bitmap.
+bool hasUnsupportedActions( const GDIMetaFile& rMtf )
+{
+ // search metafile for RasterOp action
+ MetaAction* pCurrAct;
+
+ // TODO(Q3): avoid const-cast
+ for( pCurrAct = const_cast<GDIMetaFile&>(rMtf).FirstAction();
+ pCurrAct;
+ pCurrAct = const_cast<GDIMetaFile&>(rMtf).NextAction() )
+ {
+ switch( pCurrAct->GetType() )
+ {
+ case META_RASTEROP_ACTION:
+ // overpaint is okay - that's the default, anyway
+ if( ROP_OVERPAINT ==
+ static_cast<MetaRasterOpAction*>(pCurrAct)->GetRasterOp() )
+ {
+ break;
+ }
+ // FALLTHROUGH intended
+ case META_MOVECLIPREGION_ACTION:
+ // FALLTHROUGH intended
+ case META_REFPOINT_ACTION:
+ // FALLTHROUGH intended
+ case META_WALLPAPER_ACTION:
+ return true; // at least one unsupported
+ // action encountered
+ }
+ }
+
+ return false; // no unsupported action found
+}
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper1< graphic::XGraphicRenderer > DummyRenderer_Base;
+
+class DummyRenderer :
+ public DummyRenderer_Base,
+ public cppu::BaseMutex
+{
+public:
+ DummyRenderer() :
+ DummyRenderer_Base( m_aMutex ),
+ mxGraphic()
+ {
+ }
+
+ //--- XGraphicRenderer -----------------------------------
+ virtual void SAL_CALL render( const uno::Reference< graphic::XGraphic >& rGraphic ) throw (uno::RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ mxGraphic = rGraphic;
+ }
+
+ /** Retrieve GDIMetaFile from renderer
+
+ @param bForeignSource
+ When true, the source of the metafile might be a
+ foreign application. The metafile is checked
+ against unsupported content, and, if necessary,
+ returned as a pre-rendererd bitmap.
+ */
+ GDIMetaFile getMtf( bool bForeignSource ) const
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Graphic aGraphic( mxGraphic );
+
+ if( aGraphic.GetType() == GRAPHIC_BITMAP ||
+ (bForeignSource &&
+ hasUnsupportedActions(aGraphic.GetGDIMetaFile()) ) )
+ {
+ // wrap bitmap into GDIMetafile
+ GDIMetaFile aMtf;
+ ::Point aEmptyPoint;
+
+ ::BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
+
+ aMtf.AddAction( new MetaBmpExAction( aEmptyPoint,
+ aBmpEx ) );
+ aMtf.SetPrefSize( aBmpEx.GetPrefSize() );
+ aMtf.SetPrefMapMode( aBmpEx.GetPrefMapMode() );
+
+ return aMtf;
+ }
+ else
+ {
+ return aGraphic.GetGDIMetaFile();
+ }
+ }
+
+private:
+ uno::Reference< graphic::XGraphic > mxGraphic;
+};
+
+} // anon namespace
+
+// Quick'n'dirty way: tunnel Graphic (only works for
+// in-process slideshow, of course)
+bool getMetaFile( const uno::Reference< lang::XComponent >& xSource,
+ const uno::Reference< drawing::XDrawPage >& xContainingPage,
+ GDIMetaFile& rMtf,
+ int mtfLoadFlags,
+ const uno::Reference< uno::XComponentContext >& rxContext )
+{
+ ENSURE_OR_RETURN_FALSE( rxContext.is(),
+ "getMetaFile(): Invalid context" );
+
+ // create dummy XGraphicRenderer, which receives the
+ // generated XGraphic from the GraphicExporter
+
+ // TODO(P3): Move creation of DummyRenderer out of the
+ // loop! Either by making it static, or transforming
+ // the whole thing here into a class.
+ DummyRenderer* pRenderer( new DummyRenderer() );
+ uno::Reference< graphic::XGraphicRenderer > xRenderer( pRenderer );
+
+ // -> stuff that into UnoGraphicExporter.
+ uno::Reference<lang::XMultiComponentFactory> xFactory(
+ rxContext->getServiceManager() );
+
+ OSL_ENSURE( xFactory.is(), "### no UNO?!" );
+ if( !xFactory.is() )
+ return false;
+
+ // creating the graphic exporter
+ uno::Reference< document::XExporter > xExporter(
+ xFactory->createInstanceWithContext(
+ OUSTR("com.sun.star.drawing.GraphicExportFilter"),
+ rxContext),
+ uno::UNO_QUERY );
+ uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
+
+ OSL_ENSURE( xExporter.is() && xFilter.is(), "### no graphic exporter?!" );
+ if( !xExporter.is() || !xFilter.is() )
+ return false;
+
+ uno::Sequence< beans::PropertyValue > aProps(3);
+ aProps[0].Name = OUSTR("FilterName");
+ aProps[0].Value <<= OUSTR("SVM");
+
+ aProps[1].Name = OUSTR("GraphicRenderer");
+ aProps[1].Value <<= xRenderer;
+
+ uno::Sequence< beans::PropertyValue > aFilterData(5);
+ aFilterData[0].Name = OUSTR("VerboseComments");
+ aFilterData[0].Value <<= ((mtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0);
+
+ aFilterData[1].Name = OUSTR("ScrollText");
+ aFilterData[1].Value <<= ((mtfLoadFlags & MTF_LOAD_SCROLL_TEXT_MTF) != 0);
+
+ aFilterData[2].Name = OUSTR("ExportOnlyBackground");
+ aFilterData[2].Value <<= ((mtfLoadFlags & MTF_LOAD_BACKGROUND_ONLY) != 0);
+
+ aFilterData[3].Name = OUSTR("Version");
+ aFilterData[3].Value <<= static_cast<sal_Int32>( SOFFICE_FILEFORMAT_50 );
+
+ aFilterData[4].Name = OUSTR("CurrentPage");
+ aFilterData[4].Value <<= uno::Reference< uno::XInterface >( xContainingPage,
+ uno::UNO_QUERY_THROW );
+
+ aProps[2].Name = OUSTR("FilterData");
+ aProps[2].Value <<= aFilterData;
+
+ xExporter->setSourceDocument( xSource );
+ if( !xFilter->filter( aProps ) )
+ return false;
+
+ rMtf = pRenderer->getMtf( (mtfLoadFlags & MTF_LOAD_FOREIGN_SOURCE) != 0 );
+
+ // pRenderer is automatically destroyed when xRenderer
+ // goes out of scope
+
+ // TODO(E3): Error handling. Exporter might have
+ // generated nothing, a bitmap, threw an exception,
+ // whatever.
+ return true;
+}
+
+void removeTextActions( GDIMetaFile& rMtf )
+{
+ // search metafile for text output
+ MetaAction* pCurrAct;
+
+ int nActionIndex(0);
+ pCurrAct = rMtf.FirstAction();
+ while( pCurrAct )
+ {
+ switch( pCurrAct->GetType() )
+ {
+ case META_TEXTCOLOR_ACTION:
+ case META_TEXTFILLCOLOR_ACTION:
+ case META_TEXTLINECOLOR_ACTION:
+ case META_TEXTALIGN_ACTION:
+ case META_FONT_ACTION:
+ case META_LAYOUTMODE_ACTION:
+ case META_TEXT_ACTION:
+ case META_TEXTARRAY_ACTION:
+ case META_TEXTRECT_ACTION:
+ case META_STRETCHTEXT_ACTION:
+ case META_TEXTLINE_ACTION:
+ {
+ // remove every text-related actions
+ pCurrAct = rMtf.NextAction();
+
+ rMtf.RemoveAction( nActionIndex );
+ break;
+ }
+
+ default:
+ pCurrAct = rMtf.NextAction();
+ ++nActionIndex;
+ break;
+ }
+ }
+}
+
+sal_Int32 getNextActionOffset( MetaAction * pCurrAct )
+{
+ // Special handling for actions that represent
+ // more than one indexable action
+ // ===========================================
+
+ switch (pCurrAct->GetType()) {
+ case META_TEXT_ACTION: {
+ MetaTextAction * pAct = static_cast<MetaTextAction *>(pCurrAct);
+ return (pAct->GetLen() == (USHORT)STRING_LEN
+ ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen());
+ }
+ case META_TEXTARRAY_ACTION: {
+ MetaTextArrayAction * pAct =
+ static_cast<MetaTextArrayAction *>(pCurrAct);
+ return (pAct->GetLen() == (USHORT)STRING_LEN
+ ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen());
+ }
+ case META_STRETCHTEXT_ACTION: {
+ MetaStretchTextAction * pAct =
+ static_cast<MetaStretchTextAction *>(pCurrAct);
+ return (pAct->GetLen() == (USHORT)STRING_LEN
+ ? pAct->GetText().Len() - pAct->GetIndex() : pAct->GetLen());
+ }
+ case META_FLOATTRANSPARENT_ACTION: {
+ MetaFloatTransparentAction * pAct =
+ static_cast<MetaFloatTransparentAction*>(pCurrAct);
+ // TODO(F2): Recurse into action metafile
+ // (though this is currently not used from the
+ // DrawingLayer - shape transparency gradients
+ // don't affect shape text)
+ return pAct->GetGDIMetaFile().GetActionCount();
+ }
+ default:
+ return 1;
+ }
+}
+
+bool getAnimationFromGraphic( VectorOfMtfAnimationFrames& o_rFrames,
+ ::std::size_t& o_rLoopCount,
+ CycleMode& o_eCycleMode,
+ const Graphic& rGraphic )
+{
+ o_rFrames.clear();
+
+ if( !rGraphic.IsAnimated() )
+ return false;
+
+ // some loop invariants
+ Animation aAnimation( rGraphic.GetAnimation() );
+ const Point aEmptyPoint;
+ const Size aAnimSize( aAnimation.GetDisplaySizePixel() );
+
+ // setup VDev, into which all bitmaps are painted (want to
+ // normalize animations to n bitmaps of same size. An Animation,
+ // though, can contain bitmaps of varying sizes and different
+ // update modes)
+ VirtualDevice aVDev;
+ aVDev.SetOutputSizePixel( aAnimSize );
+ aVDev.EnableMapMode( FALSE );
+
+ // setup mask VDev (alpha VDev is currently rather slow)
+ VirtualDevice aVDevMask;
+ aVDevMask.SetOutputSizePixel( aAnimSize );
+ aVDevMask.EnableMapMode( FALSE );
+
+ switch( aAnimation.GetCycleMode() )
+ {
+ case CYCLE_NOT:
+ o_rLoopCount = 1;
+ o_eCycleMode = CYCLE_LOOP;
+ break;
+
+ case CYCLE_FALLBACK:
+ // FALLTHROUGH intended
+ case CYCLE_NORMAL:
+ o_rLoopCount = aAnimation.GetLoopCount();
+ o_eCycleMode = CYCLE_LOOP;
+ break;
+
+ case CYCLE_REVERS:
+ // FALLTHROUGH intended
+ case CYCLE_REVERS_FALLBACK:
+ o_rLoopCount = aAnimation.GetLoopCount();
+ o_eCycleMode = CYCLE_PINGPONGLOOP;
+ break;
+
+ default:
+ ENSURE_OR_RETURN_FALSE(false,
+ "getAnimationFromGraphic(): Unexpected case" );
+ break;
+ }
+
+ for( USHORT i=0, nCount=aAnimation.Count(); i<nCount; ++i )
+ {
+ const AnimationBitmap& rAnimBmp( aAnimation.Get(i) );
+ switch(rAnimBmp.eDisposal)
+ {
+ case DISPOSE_NOT:
+ {
+ aVDev.DrawBitmapEx(rAnimBmp.aPosPix,
+ rAnimBmp.aBmpEx);
+ Bitmap aMask = rAnimBmp.aBmpEx.GetMask();
+
+ if( aMask.IsEmpty() )
+ {
+ const Point aEmpty;
+ const Rectangle aRect(aEmptyPoint,
+ aVDevMask.GetOutputSizePixel());
+ const Wallpaper aWallpaper(COL_BLACK);
+ aVDevMask.DrawWallpaper(aRect,
+ aWallpaper);
+ }
+ else
+ {
+ BitmapEx aTmpMask = BitmapEx(aMask,
+ aMask);
+ aVDevMask.DrawBitmapEx(rAnimBmp.aPosPix,
+ aTmpMask );
+ }
+ break;
+ }
+
+ case DISPOSE_BACK:
+ {
+ // #i70772# react on no mask
+ const Bitmap aMask(rAnimBmp.aBmpEx.GetMask());
+ const Bitmap aContent(rAnimBmp.aBmpEx.GetBitmap());
+
+ aVDevMask.Erase();
+ aVDev.DrawBitmap(rAnimBmp.aPosPix, aContent);
+
+ if(aMask.IsEmpty())
+ {
+ const Rectangle aRect(rAnimBmp.aPosPix, aContent.GetSizePixel());
+ aVDevMask.SetFillColor(COL_BLACK);
+ aVDevMask.SetLineColor();
+ aVDevMask.DrawRect(aRect);
+ }
+ else
+ {
+ aVDevMask.DrawBitmap(rAnimBmp.aPosPix, aMask);
+ }
+ break;
+ }
+
+ case DISPOSE_FULL:
+ {
+ aVDev.DrawBitmapEx(rAnimBmp.aPosPix,
+ rAnimBmp.aBmpEx);
+ break;
+ }
+
+ case DISPOSE_PREVIOUS :
+ {
+ aVDev.DrawBitmapEx(rAnimBmp.aPosPix,
+ rAnimBmp.aBmpEx);
+ aVDevMask.DrawBitmap(rAnimBmp.aPosPix,
+ rAnimBmp.aBmpEx.GetMask());
+ break;
+ }
+ }
+
+ // extract current aVDev content into a new animation
+ // frame
+ GDIMetaFileSharedPtr pMtf( new GDIMetaFile() );
+ pMtf->AddAction(
+ new MetaBmpExAction( aEmptyPoint,
+ BitmapEx(
+ aVDev.GetBitmap(
+ aEmptyPoint,
+ aAnimSize ),
+ aVDevMask.GetBitmap(
+ aEmptyPoint,
+ aAnimSize ))));
+
+ // setup mtf dimensions and pref map mode (for
+ // simplicity, keep it all in pixel. the metafile
+ // renderer scales it down to (1, 1) box anyway)
+ pMtf->SetPrefMapMode( MapMode() );
+ pMtf->SetPrefSize( aAnimSize );
+
+ // #115934#
+ // Take care of special value for MultiPage TIFFs. ATM these shall just
+ // show their first page for _quite_ some time.
+ sal_Int32 nWaitTime100thSeconds( rAnimBmp.nWait );
+ if( ANIMATION_TIMEOUT_ON_CLICK == nWaitTime100thSeconds )
+ {
+ // ATM the huge value would block the timer, so use a long
+ // time to show first page (whole day)
+ nWaitTime100thSeconds = 100 * 60 * 60 * 24;
+ }
+
+ // There are animated GIFs with no WaitTime set. Take 1 sec, then.
+ if( nWaitTime100thSeconds == 0 )
+ nWaitTime100thSeconds = 100;
+
+ o_rFrames.push_back( MtfAnimationFrame( pMtf,
+ nWaitTime100thSeconds / 100.0 ) );
+ }
+
+ return !o_rFrames.empty();
+}
+
+bool getRectanglesFromScrollMtf( ::basegfx::B2DRectangle& o_rScrollRect,
+ ::basegfx::B2DRectangle& o_rPaintRect,
+ const GDIMetaFileSharedPtr& rMtf )
+{
+ // extract bounds: scroll rect, paint rect
+ bool bScrollRectSet(false);
+ bool bPaintRectSet(false);
+
+ for ( MetaAction * pCurrAct = rMtf->FirstAction();
+ pCurrAct != 0; pCurrAct = rMtf->NextAction() )
+ {
+ if (pCurrAct->GetType() == META_COMMENT_ACTION)
+ {
+ MetaCommentAction * pAct =
+ static_cast<MetaCommentAction *>(pCurrAct);
+ // skip comment if not a special XTEXT comment
+ if (pAct->GetComment().CompareIgnoreCaseToAscii(
+ RTL_CONSTASCII_STRINGPARAM("XTEXT") ) == COMPARE_EQUAL)
+ {
+ if (pAct->GetComment().CompareIgnoreCaseToAscii(
+ "XTEXT_SCROLLRECT" ) == COMPARE_EQUAL) {
+ o_rScrollRect = ::vcl::unotools::b2DRectangleFromRectangle(
+ *reinterpret_cast<Rectangle const *>(
+ pAct->GetData() ) );
+
+ bScrollRectSet = true;
+ }
+ else if (pAct->GetComment().CompareIgnoreCaseToAscii(
+ "XTEXT_PAINTRECT" ) == COMPARE_EQUAL) {
+ o_rPaintRect = ::vcl::unotools::b2DRectangleFromRectangle(
+ *reinterpret_cast<Rectangle const *>(
+ pAct->GetData() ) );
+
+ bPaintRectSet = true;
+ }
+ }
+ }
+ }
+
+ return bScrollRectSet && bPaintRectSet;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/gdimtftools.hxx b/slideshow/source/engine/shapes/gdimtftools.hxx
new file mode 100644
index 000000000000..705c7eb35710
--- /dev/null
+++ b/slideshow/source/engine/shapes/gdimtftools.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_GDIMTFTOOLS_HXX
+#define INCLUDED_SLIDESHOW_GDIMTFTOOLS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <boost/shared_ptr.hpp>
+
+#include "tools.hxx"
+
+#include <vector>
+
+class MetaAction;
+class GDIMetaFile;
+class Graphic;
+
+// -----------------------------------------------------------------------------
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /// meta file loading specialities:
+ enum mtf_load_flags {
+ /// no flags
+ MTF_LOAD_NONE = 0,
+ /// annotate text actions with verbose comments,
+ /// denoting logical and physical text entities.
+ MTF_LOAD_VERBOSE_COMMENTS = 1,
+ /// the source of the metafile might be a foreign
+ /// application. The metafile is checked against unsupported
+ /// content, and, if necessary, returned as a pre-rendererd
+ /// bitmap.
+ MTF_LOAD_FOREIGN_SOURCE = 2,
+ /// retrieve a meta file for the page background only
+ MTF_LOAD_BACKGROUND_ONLY = 4,
+ /// retrieve the drawing layer scroll text metafile
+ MTF_LOAD_SCROLL_TEXT_MTF = 8
+ };
+
+ // Animation info
+ // ==============
+
+ struct MtfAnimationFrame
+ {
+ MtfAnimationFrame( const GDIMetaFileSharedPtr& rMtf,
+ double nDuration ) :
+ mpMtf( rMtf ),
+ mnDuration( nDuration )
+ {
+ }
+
+ /// Enables STL algos to be used for duration extraction
+ double getDuration() const
+ {
+ return mnDuration;
+ }
+
+ GDIMetaFileSharedPtr mpMtf;
+ double mnDuration;
+ };
+
+ typedef ::std::vector< MtfAnimationFrame > VectorOfMtfAnimationFrames;
+
+
+ /** Retrieve a meta file for the given shape
+
+ @param xShape
+ XShape to retrieve a metafile for.
+
+ @param xContainingPage
+ The page that contains this shape. Needed for proper
+ import (currently, the UnoGraphicExporter needs this
+ information).
+
+ @param o_rMtf
+ Metafile to extract shape content into
+ */
+ bool getMetaFile( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xSource,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xContainingPage,
+ GDIMetaFile& o_rMtf,
+ int mtfLoadFlags,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ /** Remove all text actions from the given metafile.
+ */
+ void removeTextActions( GDIMetaFile& io_rMtf );
+
+ /** Gets the next action offset for iterating meta actions which is most
+ often returns 1.
+ */
+ sal_Int32 getNextActionOffset( MetaAction * pCurrAct );
+
+ /** Extract a vector of animation frames from given Graphic.
+
+ @param o_rFrames
+ Resulting vector of animated metafiles
+
+ @param o_rLoopCount
+ Number of times the bitmap animation shall be repeated
+
+ @param o_eCycleMode
+ Repeat mode (normal, or ping-pong mode)
+
+ @param rGraphic
+ Input graphic object, to extract animations from
+ */
+ bool getAnimationFromGraphic( VectorOfMtfAnimationFrames& o_rFrames,
+ ::std::size_t& o_rLoopCount,
+ CycleMode& o_eCycleMode,
+ const Graphic& rGraphic );
+
+ /** Retrieve scroll text animation rectangles from given metafile
+
+ @return true, if both rectangles have been found, false
+ otherwise.
+ */
+ bool getRectanglesFromScrollMtf( ::basegfx::B2DRectangle& o_rScrollRect,
+ ::basegfx::B2DRectangle& o_rPaintRect,
+ const GDIMetaFileSharedPtr& rMtf );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_GDIMTFTOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/intrinsicanimationactivity.cxx b/slideshow/source/engine/shapes/intrinsicanimationactivity.cxx
new file mode 100644
index 000000000000..e185085a9787
--- /dev/null
+++ b/slideshow/source/engine/shapes/intrinsicanimationactivity.cxx
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include "drawshapesubsetting.hxx"
+#include "subsettableshapemanager.hxx"
+#include "eventqueue.hxx"
+#include "eventmultiplexer.hxx"
+#include "intrinsicanimationactivity.hxx"
+#include "intrinsicanimationeventhandler.hxx"
+
+#include <boost/noncopyable.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Activity for intrinsic shape animations
+
+ This is an Activity interface implementation for intrinsic
+ shape animations. Intrinsic shape animations are
+ animations directly within a shape, e.g. drawing layer
+ animations, or GIF animations.
+ */
+ class IntrinsicAnimationActivity : public Activity,
+ public boost::enable_shared_from_this<IntrinsicAnimationActivity>,
+ private boost::noncopyable
+ {
+ public:
+ /** Create an IntrinsicAnimationActivity.
+
+ @param rContext
+ Common slideshow objects
+
+ @param rDrawShape
+ Shape to control the intrinsic animation for
+
+ @param rWakeupEvent
+ Externally generated wakeup event, to set this
+ activity to sleep during inter-frame intervals. Must
+ come frome the outside, since wakeup event and this
+ object have mutual references to each other.
+
+ @param rTimeouts
+ Vector of timeout values, to wait before the next
+ frame is shown.
+ */
+ IntrinsicAnimationActivity( const SlideShowContext& rContext,
+ const DrawShapeSharedPtr& rDrawShape,
+ const WakeupEventSharedPtr& rWakeupEvent,
+ const ::std::vector<double>& rTimeouts,
+ ::std::size_t nNumLoops,
+ CycleMode eCycleMode );
+
+ virtual void dispose();
+ virtual double calcTimeLag() const;
+ virtual bool perform();
+ virtual bool isActive() const;
+ virtual void dequeued();
+ virtual void end();
+
+ bool enableAnimations();
+
+ private:
+ SlideShowContext maContext;
+ boost::weak_ptr<DrawShape> mpDrawShape;
+ WakeupEventSharedPtr mpWakeupEvent;
+ IntrinsicAnimationEventHandlerSharedPtr mpListener;
+ ::std::vector<double> maTimeouts;
+ CycleMode meCycleMode;
+ ::std::size_t mnCurrIndex;
+ ::std::size_t mnNumLoops;
+ ::std::size_t mnLoopCount;
+ bool mbIsActive;
+ };
+
+ //////////////////////////////////////////////////////////////////////
+
+ class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
+ private boost::noncopyable
+ {
+ public:
+ explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) :
+ mrActivity( rActivity )
+ {}
+
+ private:
+
+ virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
+ virtual bool disableAnimations() { mrActivity.end(); return true; }
+
+ IntrinsicAnimationActivity& mrActivity;
+ };
+
+ //////////////////////////////////////////////////////////////////////
+
+ IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext& rContext,
+ const DrawShapeSharedPtr& rDrawShape,
+ const WakeupEventSharedPtr& rWakeupEvent,
+ const ::std::vector<double>& rTimeouts,
+ ::std::size_t nNumLoops,
+ CycleMode eCycleMode ) :
+ maContext( rContext ),
+ mpDrawShape( rDrawShape ),
+ mpWakeupEvent( rWakeupEvent ),
+ mpListener( new IntrinsicAnimationListener(*this) ),
+ maTimeouts( rTimeouts ),
+ meCycleMode( eCycleMode ),
+ mnCurrIndex(0),
+ mnNumLoops(nNumLoops),
+ mnLoopCount(0),
+ mbIsActive(false)
+ {
+ ENSURE_OR_THROW( rContext.mpSubsettableShapeManager,
+ "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
+ ENSURE_OR_THROW( rDrawShape,
+ "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
+ ENSURE_OR_THROW( rWakeupEvent,
+ "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
+ ENSURE_OR_THROW( !rTimeouts.empty(),
+ "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
+
+ maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
+ mpListener );
+ }
+
+ void IntrinsicAnimationActivity::dispose()
+ {
+ end();
+
+ if( mpWakeupEvent )
+ mpWakeupEvent->dispose();
+
+ maContext.dispose();
+ mpDrawShape.reset();
+ mpWakeupEvent.reset();
+ maTimeouts.clear();
+ mnCurrIndex = 0;
+
+ maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
+ mpListener );
+ }
+
+ double IntrinsicAnimationActivity::calcTimeLag() const
+ {
+ return 0.0;
+ }
+
+ bool IntrinsicAnimationActivity::perform()
+ {
+ if( !isActive() )
+ return false;
+
+ DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() );
+ if( !pDrawShape || !mpWakeupEvent )
+ {
+ // event or draw shape vanished, no sense living on ->
+ // commit suicide.
+ dispose();
+ return false;
+ }
+
+ // mnNumLoops == 0 means infinite looping
+ if( mnNumLoops != 0 &&
+ mnLoopCount >= mnNumLoops )
+ {
+ // #i55294# After finishing the loops, display the first frame
+ pDrawShape->setIntrinsicAnimationFrame( 0 );
+ maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
+
+ end();
+
+ return false;
+ }
+
+ ::std::size_t nNewIndex = 0;
+ const ::std::size_t nNumFrames(maTimeouts.size());
+ switch( meCycleMode )
+ {
+ case CYCLE_LOOP:
+ {
+ pDrawShape->setIntrinsicAnimationFrame( mnCurrIndex );
+
+ mpWakeupEvent->start();
+ mpWakeupEvent->setNextTimeout( maTimeouts[mnCurrIndex] );
+
+ mnLoopCount += (mnCurrIndex + 1) / nNumFrames;
+ nNewIndex = (mnCurrIndex + 1) % nNumFrames;
+ break;
+ }
+
+ case CYCLE_PINGPONGLOOP:
+ {
+ ::std::size_t nTrueIndex( mnCurrIndex < nNumFrames ?
+ mnCurrIndex :
+ 2*nNumFrames - mnCurrIndex - 1 );
+ pDrawShape->setIntrinsicAnimationFrame( nTrueIndex );
+
+ mpWakeupEvent->start();
+ mpWakeupEvent->setNextTimeout( maTimeouts[nTrueIndex] );
+
+ mnLoopCount += (mnCurrIndex + 1) / (2*nNumFrames);
+ nNewIndex = (mnCurrIndex + 1) % 2*nNumFrames;
+ break;
+ }
+ }
+
+ maContext.mrEventQueue.addEvent( mpWakeupEvent );
+ maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
+ mnCurrIndex = nNewIndex;
+
+ return false; // don't reinsert, WakeupEvent will perform
+ // that after the given timeout
+ }
+
+ bool IntrinsicAnimationActivity::isActive() const
+ {
+ return mbIsActive;
+ }
+
+ void IntrinsicAnimationActivity::dequeued()
+ {
+ // not used here
+ }
+
+ void IntrinsicAnimationActivity::end()
+ {
+ // there is no dedicated end state, just become inactive:
+ mbIsActive = false;
+ }
+
+ bool IntrinsicAnimationActivity::enableAnimations()
+ {
+ mbIsActive = true;
+ return maContext.mrActivitiesQueue.addActivity(
+ shared_from_this() );
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ ActivitySharedPtr createIntrinsicAnimationActivity(
+ const SlideShowContext& rContext,
+ const DrawShapeSharedPtr& rDrawShape,
+ const WakeupEventSharedPtr& rWakeupEvent,
+ const ::std::vector<double>& rTimeouts,
+ ::std::size_t nNumLoops,
+ CycleMode eCycleMode )
+ {
+ return ActivitySharedPtr(
+ new IntrinsicAnimationActivity(rContext,
+ rDrawShape,
+ rWakeupEvent,
+ rTimeouts,
+ nNumLoops,
+ eCycleMode) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/intrinsicanimationactivity.hxx b/slideshow/source/engine/shapes/intrinsicanimationactivity.hxx
new file mode 100644
index 000000000000..9f626a38f6bb
--- /dev/null
+++ b/slideshow/source/engine/shapes/intrinsicanimationactivity.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_INTRINSICANIMATIONACTIVITY_HXX
+#define INCLUDED_SLIDESHOW_INTRINSICANIMATIONACTIVITY_HXX
+
+#include "wakeupevent.hxx"
+#include "activity.hxx"
+#include "slideshowcontext.hxx"
+#include "drawshape.hxx"
+#include "tools.hxx"
+
+/* Definition of IntrinsicAnimationActivity class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Create an IntrinsicAnimationActivity.
+
+ This is an Activity interface implementation for intrinsic
+ shape animations. Intrinsic shape animations are
+ animations directly within a shape, e.g. drawing layer
+ animations, or GIF animations.
+
+ @param rContext
+ Common slideshow objects
+
+ @param rDrawShape
+ Shape to control the intrinsic animation for
+
+ @param rWakeupEvent
+ Externally generated wakeup event, to set this
+ activity to sleep during inter-frame intervals. Must
+ come frome the outside, since wakeup event and this
+ object have mutual references to each other.
+
+ @param rTimeouts
+ Vector of timeout values, to wait before the next
+ frame is shown.
+ */
+ ActivitySharedPtr createIntrinsicAnimationActivity(
+ const SlideShowContext& rContext,
+ const DrawShapeSharedPtr& rDrawShape,
+ const WakeupEventSharedPtr& rWakeupEvent,
+ const ::std::vector<double>& rTimeouts,
+ ::std::size_t nNumLoops,
+ CycleMode eCycleMode );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_INTRINSICANIMATIONACTIVITY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/makefile.mk b/slideshow/source/engine/shapes/makefile.mk
new file mode 100644
index 000000000000..1d40c165707c
--- /dev/null
+++ b/slideshow/source/engine/shapes/makefile.mk
@@ -0,0 +1,60 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=slideshow
+TARGET=shapes
+ENABLE_EXCEPTIONS=TRUE
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Common ----------------------------------------------------------
+
+SLOFILES = $(SLO)$/appletshape.obj \
+ $(SLO)$/backgroundshape.obj \
+ $(SLO)$/drawinglayeranimation.obj \
+ $(SLO)$/drawshape.obj \
+ $(SLO)$/drawshapesubsetting.obj \
+ $(SLO)$/externalshapebase.obj \
+ $(SLO)$/gdimtftools.obj \
+ $(SLO)$/intrinsicanimationactivity.obj \
+ $(SLO)$/mediashape.obj \
+ $(SLO)$/shapeimporter.obj \
+ $(SLO)$/viewappletshape.obj \
+ $(SLO)$/viewbackgroundshape.obj \
+ $(SLO)$/viewmediashape.obj \
+ $(SLO)$/viewshape.obj
+
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/shapes/mediashape.cxx b/slideshow/source/engine/shapes/mediashape.cxx
new file mode 100644
index 000000000000..6d489ee736c9
--- /dev/null
+++ b/slideshow/source/engine/shapes/mediashape.cxx
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <com/sun/star/drawing/XShape.hpp>
+
+#include "mediashape.hxx"
+#include "viewmediashape.hxx"
+#include "externalshapebase.hxx"
+#include "slideshowcontext.hxx"
+#include "shape.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Represents a media shape.
+
+ This implementation offers support for media shapes.
+ Such shapes need special treatment.
+ */
+ class MediaShape : public ExternalShapeBase
+ {
+ public:
+ /** Create a shape for the given XShape for a media object
+
+ @param xShape
+ The XShape to represent.
+
+ @param nPrio
+ Externally-determined shape priority (used e.g. for
+ paint ordering). This number _must be_ unique!
+ */
+ MediaShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ double nPrio,
+ const SlideShowContext& rContext ); // throw ShapeLoadFailedException;
+
+ private:
+
+ // View layer methods
+ //------------------------------------------------------------------
+
+ virtual void addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer );
+ virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer );
+ virtual bool clearAllViewLayers();
+
+
+ // ExternalShapeBase methods
+ //------------------------------------------------------------------
+
+ virtual bool implRender( const ::basegfx::B2DRange& rCurrBounds ) const;
+ virtual void implViewChanged( const UnoViewSharedPtr& rView );
+ virtual void implViewsChanged();
+ virtual bool implStartIntrinsicAnimation();
+ virtual bool implEndIntrinsicAnimation();
+ virtual bool implPauseIntrinsicAnimation();
+ virtual bool implIsIntrinsicAnimationPlaying() const;
+ virtual void implSetIntrinsicAnimationTime(double);
+
+ /// the list of active view shapes (one for each registered view layer)
+ typedef ::std::vector< ViewMediaShapeSharedPtr > ViewMediaShapeVector;
+ ViewMediaShapeVector maViewMediaShapes;
+ bool mbIsPlaying;
+ };
+
+
+ MediaShape::MediaShape( const uno::Reference< drawing::XShape >& xShape,
+ double nPrio,
+ const SlideShowContext& rContext ) :
+ ExternalShapeBase( xShape, nPrio, rContext ),
+ maViewMediaShapes(),
+ mbIsPlaying(false)
+ {
+ }
+
+ // ---------------------------------------------------------------------
+
+ void MediaShape::implViewChanged( const UnoViewSharedPtr& rView )
+ {
+ // determine ViewMediaShape that needs update
+ ViewMediaShapeVector::const_iterator aIter(maViewMediaShapes.begin());
+ ViewMediaShapeVector::const_iterator const aEnd (maViewMediaShapes.end());
+ while( aIter != aEnd )
+ {
+ if( (*aIter)->getViewLayer()->isOnView(rView) )
+ (*aIter)->resize(getBounds());
+
+ ++aIter;
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ void MediaShape::implViewsChanged()
+ {
+ // resize all ViewShapes
+ ::std::for_each( maViewMediaShapes.begin(),
+ maViewMediaShapes.end(),
+ ::boost::bind(
+ &ViewMediaShape::resize,
+ _1,
+ ::boost::cref( getBounds())) );
+ }
+
+ // ---------------------------------------------------------------------
+
+ void MediaShape::addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer )
+ {
+ maViewMediaShapes.push_back(
+ ViewMediaShapeSharedPtr( new ViewMediaShape( rNewLayer,
+ getXShape(),
+ mxComponentContext )));
+
+ // push new size to view shape
+ maViewMediaShapes.back()->resize( getBounds() );
+
+ // render the Shape on the newly added ViewLayer
+ if( bRedrawLayer )
+ maViewMediaShapes.back()->render( getBounds() );
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::removeViewLayer( const ViewLayerSharedPtr& rLayer )
+ {
+ const ViewMediaShapeVector::iterator aEnd( maViewMediaShapes.end() );
+
+ OSL_ENSURE( ::std::count_if(maViewMediaShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewMediaShape::getViewLayer, _1 ),
+ ::boost::cref( rLayer ) ) ) < 2,
+ "MediaShape::removeViewLayer(): Duplicate ViewLayer entries!" );
+
+ ViewMediaShapeVector::iterator aIter;
+
+ if( (aIter=::std::remove_if( maViewMediaShapes.begin(),
+ aEnd,
+ ::boost::bind<bool>(
+ ::std::equal_to< ViewLayerSharedPtr >(),
+ ::boost::bind( &ViewMediaShape::getViewLayer,
+ _1 ),
+ ::boost::cref( rLayer ) ) )) == aEnd )
+ {
+ // view layer seemingly was not added, failed
+ return false;
+ }
+
+ // actually erase from container
+ maViewMediaShapes.erase( aIter, aEnd );
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::clearAllViewLayers()
+ {
+ maViewMediaShapes.clear();
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::implRender( const ::basegfx::B2DRange& rCurrBounds ) const
+ {
+ // redraw all view shapes, by calling their update() method
+ if( ::std::count_if( maViewMediaShapes.begin(),
+ maViewMediaShapes.end(),
+ ::boost::bind<bool>(
+ ::boost::mem_fn( &ViewMediaShape::render ),
+ _1,
+ ::boost::cref( rCurrBounds ) ) )
+ != static_cast<ViewMediaShapeVector::difference_type>(maViewMediaShapes.size()) )
+ {
+ // at least one of the ViewShape::update() calls did return
+ // false - update failed on at least one ViewLayer
+ return false;
+ }
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::implStartIntrinsicAnimation()
+ {
+ ::std::for_each( maViewMediaShapes.begin(),
+ maViewMediaShapes.end(),
+ ::boost::mem_fn( &ViewMediaShape::startMedia ) );
+
+ mbIsPlaying = true;
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::implEndIntrinsicAnimation()
+ {
+ ::std::for_each( maViewMediaShapes.begin(),
+ maViewMediaShapes.end(),
+ ::boost::mem_fn( &ViewMediaShape::endMedia ) );
+
+ mbIsPlaying = false;
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::implPauseIntrinsicAnimation()
+ {
+ ::std::for_each( maViewMediaShapes.begin(),
+ maViewMediaShapes.end(),
+ ::boost::mem_fn( &ViewMediaShape::pauseMedia ) );
+
+ mbIsPlaying = false;
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool MediaShape::implIsIntrinsicAnimationPlaying() const
+ {
+ return mbIsPlaying;
+ }
+
+ // ---------------------------------------------------------------------
+
+ void MediaShape::implSetIntrinsicAnimationTime(double fTime)
+ {
+ ::std::for_each( maViewMediaShapes.begin(),
+ maViewMediaShapes.end(),
+ ::boost::bind( &ViewMediaShape::setMediaTime,
+ _1, boost::cref(fTime)) );
+ }
+
+ // ---------------------------------------------------------------------
+
+ ShapeSharedPtr createMediaShape(
+ const uno::Reference< drawing::XShape >& xShape,
+ double nPrio,
+ const SlideShowContext& rContext)
+ {
+ boost::shared_ptr< MediaShape > pMediaShape(
+ new MediaShape(xShape, nPrio, rContext));
+
+ return pMediaShape;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/mediashape.hxx b/slideshow/source/engine/shapes/mediashape.hxx
new file mode 100644
index 000000000000..bd5b2988265b
--- /dev/null
+++ b/slideshow/source/engine/shapes/mediashape.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_MEDIASHAPE_HXX
+#define INCLUDED_SLIDESHOW_MEDIASHAPE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ class XShape;
+} } } }
+
+namespace slideshow
+{
+ namespace internal
+ {
+ struct SlideShowContext;
+ class Shape;
+
+ boost::shared_ptr<Shape> createMediaShape(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape,
+ double nPrio,
+ const SlideShowContext& rContext);
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_MEDIASHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/shapeimporter.cxx b/slideshow/source/engine/shapes/shapeimporter.cxx
new file mode 100644
index 000000000000..145be6645506
--- /dev/null
+++ b/slideshow/source/engine/shapes/shapeimporter.cxx
@@ -0,0 +1,679 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/stream.hxx>
+#include <svtools/grfmgr.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/streamwrap.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+#include <cppcanvas/polypolygon.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/drawing/XLayerSupplier.hpp>
+#include <com/sun/star/drawing/XLayerManager.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+
+#include "drawshapesubsetting.hxx"
+#include "drawshape.hxx"
+#include "backgroundshape.hxx"
+#include "mediashape.hxx"
+#include "appletshape.hxx"
+#include "shapeimporter.hxx"
+#include "slideshowexceptions.hxx"
+#include "gdimtftools.hxx"
+#include "tools.hxx"
+#include "slideshowcontext.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+
+using namespace com::sun::star;
+using namespace ::comphelper;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+bool importShapeGraphic(
+ GraphicObject & o_rGraphic,
+ uno::Reference<beans::XPropertySet> const& xPropSet )
+{
+ rtl::OUString aURL;
+ if( !getPropertyValue( aURL, xPropSet, OUSTR("GraphicURL")) ||
+ aURL.getLength() == 0 )
+ {
+ // no or empty property - cannot import shape graphic
+ return false;
+ }
+
+ rtl::OUString const aVndUrl(
+ RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
+ sal_Int32 nIndex( aURL.indexOf( aVndUrl ) );
+
+ if(nIndex != -1)
+ {
+ // skip past the end of the "vnd..." prefix
+ nIndex += aVndUrl.getLength();
+
+ if(nIndex >= aURL.getLength())
+ {
+ OSL_ENSURE( false, "ShapeImporter::importShape(): "
+ "embedded graphic has no graphic ID" );
+ return false;
+ }
+
+ // unique ID string found in URL, extract
+ // to separate string
+ rtl::OUString const aUniqueId(
+ aURL.copy( nIndex, aURL.getLength() - nIndex ) );
+
+ // TODO(T2): Creating a GraphicObject is not
+ // thread safe (internally calls VCL, and has
+ // unguarded internal singleton mpGlobalMgr)
+
+ // fetch already loaded graphic from graphic manager.
+ ByteString const aOldString( static_cast<String>(aUniqueId),
+ RTL_TEXTENCODING_UTF8 );
+ o_rGraphic = GraphicObject( aOldString );
+
+
+ if( GRAPHIC_DEFAULT == o_rGraphic.GetType()
+ || GRAPHIC_NONE == o_rGraphic.GetType() )
+ {
+ // even the GrfMgr does not seem to know this graphic
+ return false;
+ }
+ }
+ else
+ {
+ // no special string found, graphic must be
+ // external. Load via GraphicIm porter
+ INetURLObject aTmp( aURL );
+ boost::scoped_ptr<SvStream> pGraphicStream(
+ utl::UcbStreamHelper::CreateStream(
+ aTmp.GetMainURL( INetURLObject::NO_DECODE ),
+ STREAM_READ ) );
+ if( !pGraphicStream )
+ {
+ OSL_ENSURE( false, "ShapeImporter::importShape(): "
+ "cannot create input stream for graphic" );
+ return false;
+ }
+
+ Graphic aTmpGraphic;
+ if( GraphicConverter::Import(
+ *pGraphicStream, aTmpGraphic ) != ERRCODE_NONE )
+ {
+ OSL_ENSURE( false, "ShapeImporter::importShape(): "
+ "Failed to import shape graphic from given URL" );
+ return false;
+ }
+
+ o_rGraphic = GraphicObject( aTmpGraphic );
+ }
+ return true;
+}
+
+/** This shape implementation just acts as a dummy for the layermanager.
+ Its sole role is for hit test detection of group shapes.
+*/
+class ShapeOfGroup : public Shape
+{
+public:
+ ShapeOfGroup( ShapeSharedPtr const& pGroupShape,
+ uno::Reference<drawing::XShape> const& xShape,
+ uno::Reference<beans::XPropertySet> const& xPropSet,
+ double nPrio );
+
+ // Shape:
+ virtual uno::Reference<drawing::XShape> getXShape() const;
+ virtual void addViewLayer( ViewLayerSharedPtr const& pNewLayer,
+ bool bRedrawLayer );
+ virtual bool removeViewLayer( ViewLayerSharedPtr const& pNewLayer );
+ virtual bool clearAllViewLayers();
+ virtual bool update() const;
+ virtual bool render() const;
+ virtual bool isContentChanged() const;
+ virtual basegfx::B2DRectangle getBounds() const;
+ virtual basegfx::B2DRectangle getDomBounds() const;
+ virtual basegfx::B2DRectangle getUpdateArea() const;
+ virtual bool isVisible() const;
+ virtual double getPriority() const;
+ virtual bool isBackgroundDetached() const;
+
+private:
+ ShapeSharedPtr const mpGroupShape;
+ uno::Reference<drawing::XShape> const mxShape;
+ double const mnPrio;
+ basegfx::B2DPoint maPosOffset;
+ double mnWidth;
+ double mnHeight;
+};
+
+ShapeOfGroup::ShapeOfGroup( ShapeSharedPtr const& pGroupShape,
+ uno::Reference<drawing::XShape> const& xShape,
+ uno::Reference<beans::XPropertySet> const& xPropSet,
+ double nPrio ) :
+ mpGroupShape(pGroupShape),
+ mxShape(xShape),
+ mnPrio(nPrio)
+{
+ // read bound rect
+ uno::Any const aTmpRect_( xPropSet->getPropertyValue( OUSTR("BoundRect") ));
+ awt::Rectangle const aTmpRect( aTmpRect_.get<awt::Rectangle>() );
+ basegfx::B2DRectangle const groupPosSize( pGroupShape->getBounds() );
+ maPosOffset = basegfx::B2DPoint( aTmpRect.X - groupPosSize.getMinX(),
+ aTmpRect.Y - groupPosSize.getMinY() );
+ mnWidth = aTmpRect.Width;
+ mnHeight = aTmpRect.Height;
+}
+
+uno::Reference<drawing::XShape> ShapeOfGroup::getXShape() const
+{
+ return mxShape;
+}
+
+void ShapeOfGroup::addViewLayer( ViewLayerSharedPtr const& /*pNewLayer*/,
+ bool /*bRedrawLayer*/ )
+{
+}
+
+bool ShapeOfGroup::removeViewLayer( ViewLayerSharedPtr const& /*pNewLayer*/ )
+{
+ return true;
+}
+
+bool ShapeOfGroup::clearAllViewLayers()
+{
+ return true;
+}
+
+bool ShapeOfGroup::update() const
+{
+ return true;
+}
+
+bool ShapeOfGroup::render() const
+{
+ return true;
+}
+
+bool ShapeOfGroup::isContentChanged() const
+{
+ return false;
+}
+
+basegfx::B2DRectangle ShapeOfGroup::getBounds() const
+{
+ basegfx::B2DRectangle const groupPosSize( mpGroupShape->getBounds() );
+ double const posX = (groupPosSize.getMinX() + maPosOffset.getX());
+ double const posY = (groupPosSize.getMinY() + maPosOffset.getY());
+ return basegfx::B2DRectangle( posX, posY, posX + mnWidth, posY + mnHeight );
+}
+
+basegfx::B2DRectangle ShapeOfGroup::getDomBounds() const
+{
+ return getBounds();
+}
+
+basegfx::B2DRectangle ShapeOfGroup::getUpdateArea() const
+{
+ return getBounds();
+}
+
+bool ShapeOfGroup::isVisible() const
+{
+ return mpGroupShape->isVisible();
+}
+
+double ShapeOfGroup::getPriority() const
+{
+ return mnPrio;
+}
+
+bool ShapeOfGroup::isBackgroundDetached() const
+{
+ return false;
+}
+
+} // anon namespace
+
+ShapeSharedPtr ShapeImporter::createShape(
+ uno::Reference<drawing::XShape> const& xCurrShape,
+ uno::Reference<beans::XPropertySet> const& xPropSet,
+ rtl::OUString const& shapeType ) const
+{
+ if( shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.MediaShape") ) ||
+ shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.MediaShape") ) )
+ {
+ // Media shape (video etc.). This is a special object
+ return createMediaShape(xCurrShape,
+ mnAscendingPrio,
+ mrContext);
+ }
+ else if( shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.PluginShape") ))
+ {
+ // PropertyValues to copy from XShape to plugin
+ static const char* aPropertyValues[] =
+ {
+ "PluginURL",
+ "PluginMimeType",
+ "PluginCommands"
+ };
+
+ // (Netscape)Plugin shape. This is a special object
+ return createAppletShape( xCurrShape,
+ mnAscendingPrio,
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.sfx2.PluginObject" )),
+ aPropertyValues,
+ sizeof(aPropertyValues)/sizeof(*aPropertyValues),
+ mrContext );
+ }
+ else if( shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.AppletShape") ))
+ {
+ // PropertyValues to copy from XShape to applet
+ static const char* aPropertyValues[] =
+ {
+ "AppletCodeBase",
+ "AppletName",
+ "AppletCode",
+ "AppletCommands",
+ "AppletIsScript"
+ };
+
+ // (Java)Applet shape. This is a special object
+ return createAppletShape( xCurrShape,
+ mnAscendingPrio,
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.comp.sfx2.AppletObject" )),
+ aPropertyValues,
+ sizeof(aPropertyValues)/sizeof(*aPropertyValues),
+ mrContext );
+ }
+ else if( shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.OLE2Shape") ) ||
+ shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.OLE2Shape") ) )
+ {
+ // #i46224# Mark OLE shapes as foreign content - scan them for
+ // unsupported actions, and fallback to bitmap, if necessary
+ return DrawShape::create( xCurrShape,
+ mxPage,
+ mnAscendingPrio,
+ true,
+ mrContext );
+ }
+ else if( shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.drawing.GraphicObjectShape") ) ||
+ shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.presentation.GraphicObjectShape") ) )
+ {
+ GraphicObject aGraphicObject;
+
+ // to get hold of GIF animations, inspect Graphic
+ // objects more thoroughly (the plain-jane shape
+ // metafile of course would only contain the first
+ // animation frame)
+ if( !importShapeGraphic( aGraphicObject, xPropSet ) )
+ return ShapeSharedPtr(); // error loading graphic -
+ // #142147# no placeholders in
+ // slideshow
+
+ if( !aGraphicObject.IsAnimated() )
+ {
+ // no animation - simply utilize plain draw shape import
+
+ // import shape as bitmap - either its a bitmap
+ // anyway, or its a metafile, which currently the
+ // metafile renderer might not display correctly.
+ return DrawShape::create( xCurrShape,
+ mxPage,
+ mnAscendingPrio,
+ true,
+ mrContext );
+ }
+
+
+ // now extract relevant shape attributes via API
+ // ---------------------------------------------
+
+ drawing::ColorMode eColorMode( drawing::ColorMode_STANDARD );
+ sal_Int16 nLuminance(0);
+ sal_Int16 nContrast(0);
+ sal_Int16 nRed(0);
+ sal_Int16 nGreen(0);
+ sal_Int16 nBlue(0);
+ double nGamma(1.0);
+ sal_Int16 nTransparency(0);
+ sal_Int32 nRotation(0);
+
+ getPropertyValue( eColorMode, xPropSet, OUSTR("GraphicColorMode") );
+ getPropertyValue( nLuminance, xPropSet, OUSTR("AdjustLuminance") );
+ getPropertyValue( nContrast, xPropSet, OUSTR("AdjustContrast") );
+ getPropertyValue( nRed, xPropSet, OUSTR("AdjustRed") );
+ getPropertyValue( nGreen, xPropSet, OUSTR("AdjustGreen") );
+ getPropertyValue( nBlue, xPropSet, OUSTR("AdjustBlue") );
+ getPropertyValue( nGamma, xPropSet, OUSTR("Gamma") );
+ getPropertyValue( nTransparency, xPropSet, OUSTR("Transparency") );
+ getPropertyValue( nRotation, xPropSet, OUSTR("RotateAngle") );
+
+ GraphicAttr aGraphAttrs;
+ aGraphAttrs.SetDrawMode( (GraphicDrawMode)eColorMode );
+ aGraphAttrs.SetLuminance( nLuminance );
+ aGraphAttrs.SetContrast( nContrast );
+ aGraphAttrs.SetChannelR( nRed );
+ aGraphAttrs.SetChannelG( nGreen );
+ aGraphAttrs.SetChannelB( nBlue );
+ aGraphAttrs.SetGamma( nGamma );
+ aGraphAttrs.SetTransparency( static_cast<BYTE>(nTransparency) );
+ aGraphAttrs.SetRotation( static_cast<USHORT>(nRotation*10) );
+
+ text::GraphicCrop aGraphCrop;
+ if( getPropertyValue( aGraphCrop, xPropSet, OUSTR("GraphicCrop") ))
+ {
+ aGraphAttrs.SetCrop( aGraphCrop.Left,
+ aGraphCrop.Top,
+ aGraphCrop.Right,
+ aGraphCrop.Bottom );
+ }
+
+ // fetch readily transformed and color-modified
+ // graphic
+ // ---------------------------------------------
+
+ Graphic aGraphic(
+ aGraphicObject.GetTransformedGraphic(
+ aGraphicObject.GetPrefSize(),
+ aGraphicObject.GetPrefMapMode(),
+ aGraphAttrs ) );
+
+ return DrawShape::create( xCurrShape,
+ mxPage,
+ mnAscendingPrio,
+ aGraphic,
+ mrContext );
+ }
+ else
+ {
+ return DrawShape::create( xCurrShape,
+ mxPage,
+ mnAscendingPrio,
+ false,
+ mrContext );
+ }
+}
+
+bool ShapeImporter::isSkip(
+ uno::Reference<beans::XPropertySet> const& xPropSet,
+ rtl::OUString const& shapeType,
+ uno::Reference< drawing::XLayer> const& xLayer )
+{
+ // skip empty presentation objects:
+ bool bEmpty = false;
+ if( getPropertyValue( bEmpty,
+ xPropSet,
+ OUSTR("IsEmptyPresentationObject")) &&
+ bEmpty )
+ {
+ return true;
+ }
+
+ //skip shapes which corresponds to annotations
+ if(xLayer.is())
+ {
+ rtl::OUString layerName;
+ uno::Reference<beans::XPropertySet> xPropLayerSet(
+ xLayer, uno::UNO_QUERY );
+ const uno::Any& a(xPropLayerSet->getPropertyValue(rtl::OUString::createFromAscii("Name")) );
+ bool const bRet = (a >>= layerName);
+ if(bRet)
+ {
+ if( layerName.equals(rtl::OUString::createFromAscii("DrawnInSlideshow")))
+ {
+ //Transform shapes into PolyPolygons
+ importPolygons(xPropSet);
+
+ return true;
+ }
+ }
+ }
+
+ // don't export presentation placeholders on masterpage
+ // they can be non empty when user edits the default texts
+ if(mbConvertingMasterPage)
+ {
+ if(shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation."
+ "TitleTextShape") ) ||
+ shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation."
+ "OutlinerShape") ))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void ShapeImporter::importPolygons(uno::Reference<beans::XPropertySet> const& xPropSet) {
+
+ drawing::PointSequenceSequence aRetval;
+ sal_Int32 nLineColor=0;
+ double fLineWidth;
+ getPropertyValue( aRetval, xPropSet, OUSTR("PolyPolygon") );
+ getPropertyValue( nLineColor, xPropSet, OUSTR("LineColor") );
+ getPropertyValue( fLineWidth, xPropSet, OUSTR("LineWidth") );
+
+ drawing::PointSequence* pOuterSequence = aRetval.getArray();
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+
+ ::basegfx::B2DPolygon aPoly;
+ basegfx::B2DPoint aPoint;
+ for( sal_Int32 nCurrPoly=0; nCurrPoly<pOuterSequence->getLength(); ++nCurrPoly, ++pInnerSequence )
+ {
+ aPoint.setX((*pInnerSequence).X);
+ aPoint.setY((*pInnerSequence).Y);
+ aPoly.append( aPoint );
+ }
+ UnoViewVector::const_iterator aIter=(mrContext.mrViewContainer).begin();
+ UnoViewVector::const_iterator aEnd=(mrContext.mrViewContainer).end();
+ while(aIter != aEnd)
+ {
+ ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
+ ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( (*aIter)->getCanvas(),
+ aPoly ) );
+ if( pPolyPoly )
+ {
+ pPolyPoly->setRGBALineColor( unoColor2RGBColor( nLineColor ).getIntegerColor() );
+ pPolyPoly->setStrokeWidth(fLineWidth);
+ pPolyPoly->draw();
+ maPolygons.push_back(pPolyPoly);
+ }
+ aIter++;
+ }
+}
+
+ShapeSharedPtr ShapeImporter::importBackgroundShape() // throw (ShapeLoadFailedException)
+{
+ if( maShapesStack.empty() )
+ throw ShapeLoadFailedException();
+
+ XShapesEntry& rTop = maShapesStack.top();
+ ShapeSharedPtr pBgShape(
+ createBackgroundShape(mxPage,
+ uno::Reference<drawing::XDrawPage>(
+ rTop.mxShapes,
+ uno::UNO_QUERY_THROW),
+ mrContext) );
+ mnAscendingPrio += 1.0;
+
+ return pBgShape;
+}
+
+ShapeSharedPtr ShapeImporter::importShape() // throw (ShapeLoadFailedException)
+{
+ ShapeSharedPtr pRet;
+ bool bIsGroupShape = false;
+
+ while( !maShapesStack.empty() && !pRet )
+ {
+ XShapesEntry& rTop = maShapesStack.top();
+ if( rTop.mnPos < rTop.mnCount )
+ {
+ uno::Reference<drawing::XShape> const xCurrShape(
+ rTop.mxShapes->getByIndex( rTop.mnPos ), uno::UNO_QUERY );
+ ++rTop.mnPos;
+ uno::Reference<beans::XPropertySet> xPropSet(
+ xCurrShape, uno::UNO_QUERY );
+ if( !xPropSet.is() )
+ {
+ // we definitely need the properties of
+ // the shape here. This will also fail,
+ // if getByIndex did not return a valid
+ // shape
+ throw ShapeLoadFailedException();
+ }
+
+ //Retrieve the layer for the current shape
+ uno::Reference< drawing::XLayer > xDrawnInSlideshow;
+
+ uno::Reference< drawing::XLayerSupplier > xLayerSupplier(mxPagesSupplier, uno::UNO_QUERY);
+ if(xLayerSupplier.is())
+ {
+ uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
+
+ uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
+
+ xDrawnInSlideshow = xLayerManager->getLayerForShape(xCurrShape);
+ }
+
+ rtl::OUString const shapeType( xCurrShape->getShapeType());
+
+ // is this shape presentation-invisible?
+ if( !isSkip(xPropSet, shapeType, xDrawnInSlideshow) )
+ {
+ bIsGroupShape = shapeType.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(
+ "com.sun.star.drawing.GroupShape") );
+
+ if( rTop.mpGroupShape ) // in group particle mode?
+ {
+ pRet.reset( new ShapeOfGroup(
+ rTop.mpGroupShape /* container shape */,
+ xCurrShape, xPropSet,
+ mnAscendingPrio ) );
+ }
+ else
+ {
+ pRet = createShape( xCurrShape, xPropSet, shapeType );
+ }
+ mnAscendingPrio += 1.0;
+ }
+ }
+ if( rTop.mnPos >= rTop.mnCount )
+ {
+ // group or top-level shapes finished:
+ maShapesStack.pop();
+ }
+ if( bIsGroupShape && pRet )
+ {
+ // push new group on the stack: group traversal
+ maShapesStack.push( XShapesEntry( pRet ) );
+ }
+ }
+
+ return pRet;
+}
+
+bool ShapeImporter::isImportDone() const
+{
+ return maShapesStack.empty();
+}
+
+PolyPolygonVector ShapeImporter::getPolygons()
+{
+ return maPolygons;
+}
+
+ShapeImporter::ShapeImporter( uno::Reference<drawing::XDrawPage> const& xPage,
+ uno::Reference<drawing::XDrawPage> const& xActualPage,
+ uno::Reference<drawing::XDrawPagesSupplier> const& xPagesSupplier,
+ const SlideShowContext& rContext,
+ sal_Int32 nOrdNumStart,
+ bool bConvertingMasterPage ) :
+ mxPage( xActualPage ),
+#ifdef ENABLE_PRESENTER_EXTRA_UI
+ mxPagesSupplier( xPagesSupplier ),
+#else
+ mxPagesSupplier( NULL ),
+#endif
+ mrContext( rContext ),
+ maPolygons(),
+ maShapesStack(),
+ mnAscendingPrio( nOrdNumStart ),
+ mbConvertingMasterPage( bConvertingMasterPage )
+{
+#ifndef ENABLE_PRESENTER_EXTRA_UI
+ (void)xPagesSupplier;
+#endif
+ uno::Reference<drawing::XShapes> const xShapes(
+ xPage, uno::UNO_QUERY_THROW );
+ maShapesStack.push( XShapesEntry(xShapes) );
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewappletshape.cxx b/slideshow/source/engine/shapes/viewappletshape.cxx
new file mode 100644
index 000000000000..1af40d99a742
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewappletshape.cxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/verbosetrace.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/debug.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <cppcanvas/spritecanvas.hxx>
+#include <canvas/canvastools.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/XToolkit.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
+
+#include "viewappletshape.hxx"
+#include "tools.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ViewAppletShape::ViewAppletShape( const ViewLayerSharedPtr& rViewLayer,
+ const uno::Reference< drawing::XShape >& rxShape,
+ const ::rtl::OUString& rServiceName,
+ const char** pPropCopyTable,
+ sal_Size nNumPropEntries,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ mpViewLayer( rViewLayer ),
+ mxViewer(),
+ mxFrame(),
+ mxComponentContext( rxContext )
+ {
+ ENSURE_OR_THROW( rxShape.is(), "ViewAppletShape::ViewAppletShape(): Invalid Shape" );
+ ENSURE_OR_THROW( mpViewLayer, "ViewAppletShape::ViewAppletShape(): Invalid View" );
+ ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewAppletShape::ViewAppletShape(): Invalid ViewLayer canvas" );
+ ENSURE_OR_THROW( mxComponentContext.is(), "ViewAppletShape::ViewAppletShape(): Invalid component context" );
+
+ uno::Reference<lang::XMultiComponentFactory> xFactory(
+ mxComponentContext->getServiceManager(),
+ uno::UNO_QUERY_THROW );
+
+ mxViewer.set( xFactory->createInstanceWithContext( rServiceName,
+ mxComponentContext),
+ uno::UNO_QUERY_THROW );
+
+ uno::Reference< beans::XPropertySet > xShapePropSet( rxShape,
+ uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > mxViewerPropSet( mxViewer,
+ uno::UNO_QUERY_THROW );
+
+ // copy shape properties to applet viewer
+ ::rtl::OUString aPropName;
+ for( sal_Size i=0; i<nNumPropEntries; ++i )
+ {
+ aPropName = ::rtl::OUString::createFromAscii( pPropCopyTable[i] );
+ mxViewerPropSet->setPropertyValue( aPropName,
+ xShapePropSet->getPropertyValue(
+ aPropName ));
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ ViewAppletShape::~ViewAppletShape()
+ {
+ try
+ {
+ endApplet();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ ViewLayerSharedPtr ViewAppletShape::getViewLayer() const
+ {
+ return mpViewLayer;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewAppletShape::startApplet( const ::basegfx::B2DRectangle& rBounds )
+ {
+ ENSURE_OR_RETURN_FALSE( mpViewLayer && mpViewLayer->getCanvas() && mpViewLayer->getCanvas()->getUNOCanvas().is(),
+ "ViewAppletShape::startApplet(): Invalid or disposed view" );
+ try
+ {
+ ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();
+
+ uno::Reference< beans::XPropertySet > xPropSet( pCanvas->getUNOCanvas()->getDevice(),
+ uno::UNO_QUERY_THROW );
+
+ uno::Reference< awt::XWindow2 > xParentWindow(
+ xPropSet->getPropertyValue(
+ ::rtl::OUString::createFromAscii( "Window" )),
+ uno::UNO_QUERY_THROW );
+
+ uno::Reference<lang::XMultiComponentFactory> xFactory(
+ mxComponentContext->getServiceManager() );
+
+ if( xFactory.is() )
+ {
+ // create an awt window to contain the applet
+ // ==========================================
+
+ uno::Reference< awt::XToolkit > xToolkit(
+ xFactory->createInstanceWithContext(
+ ::rtl::OUString::createFromAscii( "com.sun.star.awt.Toolkit" ),
+ mxComponentContext ),
+ uno::UNO_QUERY_THROW );
+
+ awt::WindowDescriptor aOwnWinDescriptor( awt::WindowClass_SIMPLE,
+ ::rtl::OUString(),
+ uno::Reference< awt::XWindowPeer >(xParentWindow,
+ uno::UNO_QUERY_THROW),
+ 0,
+ awt::Rectangle(),
+ awt::WindowAttribute::SHOW
+ | awt::VclWindowPeerAttribute::CLIPCHILDREN );
+
+ uno::Reference< awt::XWindowPeer > xNewWinPeer(
+ xToolkit->createWindow( aOwnWinDescriptor ));
+ uno::Reference< awt::XWindow > xOwnWindow( xNewWinPeer,
+ uno::UNO_QUERY_THROW );
+
+
+ // create a frame, and load the applet into it
+ // ===========================================
+
+ mxFrame.set(
+ xFactory->createInstanceWithContext(
+ ::rtl::OUString::createFromAscii( "com.sun.star.frame.Frame" ),
+ mxComponentContext ),
+ uno::UNO_QUERY_THROW );
+
+ mxFrame->initialize( xOwnWindow );
+
+ uno::Reference < frame::XSynchronousFrameLoader > xLoader( mxViewer,
+ uno::UNO_QUERY_THROW );
+ xLoader->load( uno::Sequence < beans::PropertyValue >(),
+ mxFrame );
+
+
+ // resize surrounding window and applet to current shape size
+ // ==========================================================
+
+ ::basegfx::B2DRange aTmpRange;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRange,
+ rBounds,
+ mpViewLayer->getTransformation() );
+ const ::basegfx::B2IRange& rPixelBounds(
+ ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
+
+ uno::Reference< awt::XWindow > xSurroundingWindow( mxFrame->getContainerWindow() );
+ if( xSurroundingWindow.is() )
+ xSurroundingWindow->setPosSize( static_cast<sal_Int32>(rPixelBounds.getMinX()),
+ static_cast<sal_Int32>(rPixelBounds.getMinY()),
+ static_cast<sal_Int32>(rPixelBounds.getWidth()),
+ static_cast<sal_Int32>(rPixelBounds.getHeight()),
+ awt::PosSize::POSSIZE );
+
+ uno::Reference< awt::XWindow > xAppletWindow( mxFrame->getComponentWindow() );
+ if( xAppletWindow.is() )
+ xAppletWindow->setPosSize( 0, 0,
+ static_cast<sal_Int32>(rPixelBounds.getWidth()),
+ static_cast<sal_Int32>(rPixelBounds.getHeight()),
+ awt::PosSize::POSSIZE );
+ }
+ }
+ catch (uno::Exception &)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ViewAppletShape::endApplet()
+ {
+ uno::Reference<util::XCloseable> xCloseable(
+ mxFrame,
+ uno::UNO_QUERY );
+
+ if( xCloseable.is() )
+ {
+ xCloseable->close( sal_True );
+ mxFrame.clear();
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewAppletShape::render( const ::basegfx::B2DRectangle& rBounds ) const
+ {
+ ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();
+
+ if( !pCanvas )
+ return false;
+
+ if( !mxFrame.is() )
+ {
+ // fill the shape background with black
+ fillRect( pCanvas,
+ rBounds,
+ 0xFFFFFFFFU );
+ }
+
+ return true;
+ }
+
+ bool ViewAppletShape::resize( const ::basegfx::B2DRectangle& rBounds ) const
+ {
+ if( !mxFrame.is() )
+ return false;
+
+ ::basegfx::B2DRange aTmpRange;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRange,
+ rBounds,
+ mpViewLayer->getTransformation() );
+ const ::basegfx::B2IRange& rPixelBounds(
+ ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
+
+ uno::Reference< awt::XWindow > xFrameWindow( mxFrame->getContainerWindow() );
+ if( xFrameWindow.is() )
+ xFrameWindow->setPosSize( static_cast<sal_Int32>(rPixelBounds.getMinX()),
+ static_cast<sal_Int32>(rPixelBounds.getMinY()),
+ static_cast<sal_Int32>(rPixelBounds.getWidth()),
+ static_cast<sal_Int32>(rPixelBounds.getHeight()),
+ awt::PosSize::POSSIZE );
+
+ uno::Reference< awt::XWindow > xAppletWindow( mxFrame->getComponentWindow() );
+ if( xAppletWindow.is() )
+ xAppletWindow->setPosSize( 0, 0,
+ static_cast<sal_Int32>(rPixelBounds.getWidth()),
+ static_cast<sal_Int32>(rPixelBounds.getHeight()),
+ awt::PosSize::POSSIZE );
+
+ return true;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewappletshape.hxx b/slideshow/source/engine/shapes/viewappletshape.hxx
new file mode 100644
index 000000000000..b80b89f51254
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewappletshape.hxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWAPPLETSHAPE_HXX
+#define INCLUDED_SLIDESHOW_VIEWAPPLETSHAPE_HXX
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <com/sun/star/awt/Point.hpp>
+
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "viewlayer.hxx"
+
+namespace com { namespace sun { namespace star {
+namespace frame {
+ class XSynchronousFrameLoader;
+ class XFrame;
+}
+namespace uno {
+ class XComponentContext;
+}
+namespace drawing {
+ class XShape;
+}}}}
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class is the viewable representation of a draw
+ document's applet object, associated to a specific View
+
+ The class is able to render the associated applet on View
+ implementations.
+ */
+ class ViewAppletShape : private boost::noncopyable
+ {
+ public:
+ /** Create a ViewAppletShape for the given View
+
+ @param rViewLayer
+ The associated View object.
+
+ @param rxShape
+ The associated Shape
+
+ @param rServiceName
+ The service name to use, when actually creating the
+ viewer component
+
+ @param pPropCopyTable
+ Table of plain ASCII property names, to copy from
+ xShape to applet.
+
+ @param nNumPropEntries
+ Number of property table entries (in pPropCopyTable)
+ */
+ ViewAppletShape( const ViewLayerSharedPtr& rViewLayer,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& rxShape,
+ const ::rtl::OUString& rServiceName,
+ const char** pPropCopyTable,
+ sal_Size nNumPropEntries,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ /** destroy the object
+ */
+ virtual ~ViewAppletShape();
+
+ /** Query the associated view layer of this shape
+ */
+ ViewLayerSharedPtr getViewLayer() const;
+
+ // animation methods
+ //------------------------------------------------------------------
+
+ /** Notify the ViewShape that an animation starts now
+
+ This method enters animation mode on the associate
+ target view. The shape can be animated in parallel on
+ different views.
+
+ @param rBounds
+ The current applet shape bounds
+
+ @return whether the mode change finished successfully.
+ */
+ bool startApplet( const ::basegfx::B2DRectangle& rBounds );
+
+ /** Notify the ViewShape that it is no longer animated
+
+ This methods ends animation mode on the associate
+ target view
+ */
+ void endApplet();
+
+ // render methods
+ //------------------------------------------------------------------
+
+ /** Render the ViewShape
+
+ This method renders the ViewAppletShape on the associated view.
+
+ @param rBounds
+ The current applet shape bounds
+
+ @return whether the rendering finished successfully.
+ */
+ bool render( const ::basegfx::B2DRectangle& rBounds ) const;
+
+ /** Resize the ViewShape
+
+ This method resizes the ViewAppletShape on the
+ associated view. It does not render.
+
+ @param rBounds
+ The current applet shape bounds
+
+ @return whether the resize finished successfully.
+ */
+ bool resize( const ::basegfx::B2DRectangle& rBounds ) const;
+
+ private:
+
+ ViewLayerSharedPtr mpViewLayer;
+
+ /// the actual viewer component for this applet
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::frame::XSynchronousFrameLoader> mxViewer;
+
+ /// the frame containing the applet
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::frame::XFrame> mxFrame;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext> mxComponentContext;
+ };
+
+ typedef ::boost::shared_ptr< ViewAppletShape > ViewAppletShapeSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWAPPLETSHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewbackgroundshape.cxx b/slideshow/source/engine/shapes/viewbackgroundshape.cxx
new file mode 100644
index 000000000000..e849017b00a0
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewbackgroundshape.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "viewbackgroundshape.hxx"
+#include "tools.hxx"
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+#include <cppcanvas/renderer.hxx>
+#include <cppcanvas/bitmap.hxx>
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ bool ViewBackgroundShape::prefetch( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewBackgroundShape::prefetch()" );
+ ENSURE_OR_RETURN_FALSE( rMtf,
+ "ViewBackgroundShape::prefetch(): no valid metafile!" );
+
+ const ::basegfx::B2DHomMatrix& rCanvasTransform(
+ mpViewLayer->getTransformation() );
+
+ if( !mxBitmap.is() ||
+ rMtf != mpLastMtf ||
+ rCanvasTransform != maLastTransformation )
+ {
+ // buffered bitmap is invalid, re-create
+
+ // determine transformed page bounds
+ ::basegfx::B2DRectangle aTmpRect;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRect,
+ maBounds,
+ rCanvasTransform );
+
+ // determine pixel size of bitmap (choose it one pixel
+ // larger, as polygon rendering takes one pixel more
+ // to the right and to the bottom)
+ const ::basegfx::B2ISize aBmpSizePixel(
+ ::basegfx::fround( aTmpRect.getRange().getX() + 1),
+ ::basegfx::fround( aTmpRect.getRange().getY() + 1) );
+
+ // create a bitmap of appropriate size
+ ::cppcanvas::BitmapSharedPtr pBitmap(
+ ::cppcanvas::BaseGfxFactory::getInstance().createBitmap(
+ rDestinationCanvas,
+ aBmpSizePixel ) );
+
+ ENSURE_OR_THROW( pBitmap,
+ "ViewBackgroundShape::prefetch(): Cannot create background bitmap" );
+
+ ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
+
+ ENSURE_OR_THROW( pBitmapCanvas,
+ "ViewBackgroundShape::prefetch(): Cannot create background bitmap canvas" );
+
+ // clear bitmap
+ initSlideBackground( pBitmapCanvas,
+ aBmpSizePixel );
+
+ // apply linear part of destination canvas transformation (linear means in this context:
+ // transformation without any translational components)
+ ::basegfx::B2DHomMatrix aLinearTransform( rCanvasTransform );
+ aLinearTransform.set( 0, 2, 0.0 );
+ aLinearTransform.set( 1, 2, 0.0 );
+ pBitmapCanvas->setTransformation( aLinearTransform );
+
+ const basegfx::B2DHomMatrix aShapeTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(
+ maBounds.getWidth(), maBounds.getHeight(),
+ maBounds.getMinX(), maBounds.getMinY()));
+
+ ::cppcanvas::RendererSharedPtr pRenderer(
+ ::cppcanvas::VCLFactory::getInstance().createRenderer(
+ pBitmapCanvas,
+ *rMtf.get(),
+ ::cppcanvas::Renderer::Parameters() ) );
+
+ ENSURE_OR_RETURN_FALSE( pRenderer,
+ "ViewBackgroundShape::prefetch(): Could not create Renderer" );
+
+ pRenderer->setTransformation( aShapeTransform );
+ pRenderer->draw();
+
+ mxBitmap = pBitmap->getUNOBitmap();
+ }
+
+ mpLastMtf = rMtf;
+ maLastTransformation = rCanvasTransform;
+
+ return mxBitmap.is();
+ }
+
+ ViewBackgroundShape::ViewBackgroundShape( const ViewLayerSharedPtr& rViewLayer,
+ const ::basegfx::B2DRectangle& rShapeBounds ) :
+ mpViewLayer( rViewLayer ),
+ mxBitmap(),
+ mpLastMtf(),
+ maLastTransformation(),
+ maBounds( rShapeBounds )
+ {
+ ENSURE_OR_THROW( mpViewLayer, "ViewBackgroundShape::ViewBackgroundShape(): Invalid View" );
+ ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewBackgroundShape::ViewBackgroundShape(): Invalid ViewLayer canvas" );
+ }
+
+ ViewLayerSharedPtr ViewBackgroundShape::getViewLayer() const
+ {
+ return mpViewLayer;
+ }
+
+ bool ViewBackgroundShape::render( const GDIMetaFileSharedPtr& rMtf ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewBackgroundShape::draw()" );
+
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas( mpViewLayer->getCanvas() );
+
+ if( !prefetch( rDestinationCanvas, rMtf ) )
+ return false;
+
+ ENSURE_OR_RETURN_FALSE( mxBitmap.is(),
+ "ViewBackgroundShape::draw(): Invalid background bitmap" );
+
+ ::basegfx::B2DHomMatrix aTransform( mpViewLayer->getTransformation() );
+
+ // invert the linear part of the view transformation
+ // (i.e. the view transformation without translational
+ // components), to be able to leave the canvas
+ // transformation intact (would otherwise destroy possible
+ // clippings, as the clip polygon is relative to the view
+ // coordinate system).
+ aTransform.set(0,2, 0.0 );
+ aTransform.set(1,2, 0.0 );
+ aTransform.invert();
+
+ rendering::RenderState aRenderState;
+ ::canvas::tools::initRenderState( aRenderState );
+
+ ::canvas::tools::setRenderStateTransform( aRenderState, aTransform );
+
+ try
+ {
+ rDestinationCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
+ rDestinationCanvas->getViewState(),
+ aRenderState );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewbackgroundshape.hxx b/slideshow/source/engine/shapes/viewbackgroundshape.hxx
new file mode 100644
index 000000000000..cd561a7129ec
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewbackgroundshape.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWBACKGROUNDSHAPE_HXX
+#define INCLUDED_SLIDESHOW_VIEWBACKGROUNDSHAPE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/rendering/XBitmap.hpp>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <cppcanvas/spritecanvas.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include "gdimtftools.hxx"
+#include "viewlayer.hxx"
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class is the viewable representation of a draw
+ document's background, associated to a specific View
+
+ The class is able to render the associated background on
+ View implementations.
+ */
+ class ViewBackgroundShape : private boost::noncopyable
+ {
+ public:
+ /** Create a ViewBackgroundShape for the given View
+
+ @param rView
+ The associated View object.
+
+ @param rShapeBounds
+ Bounds of the background shape, in document coordinate
+ system.
+ */
+ ViewBackgroundShape( const ViewLayerSharedPtr& rViewLayer,
+ const ::basegfx::B2DRectangle& rShapeBounds );
+
+ /** Query the associated view layer of this shape
+ */
+ ViewLayerSharedPtr getViewLayer() const;
+
+ bool render( const GDIMetaFileSharedPtr& rMtf ) const;
+
+ private:
+ /** Prefetch bitmap for given canvas
+ */
+ bool prefetch( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf ) const;
+
+ /** The view layer this object is part of.
+ */
+ ViewLayerSharedPtr mpViewLayer;
+
+ /// Generated content bitmap, already with correct output size
+ mutable ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > mxBitmap;
+
+ /// The last metafile a render object was generated for
+ mutable GDIMetaFileSharedPtr mpLastMtf;
+
+ /// The canvas, mpRenderer is associated with
+ mutable ::basegfx::B2DHomMatrix maLastTransformation;
+
+ const ::basegfx::B2DRectangle maBounds;
+ };
+
+ typedef ::boost::shared_ptr< ViewBackgroundShape > ViewBackgroundShapeSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWBACKGROUNDSHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewmediashape.cxx b/slideshow/source/engine/shapes/viewmediashape.cxx
new file mode 100644
index 000000000000..def413f3167b
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewmediashape.cxx
@@ -0,0 +1,575 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <math.h>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <vcl/window.hxx>
+#include <vcl/javachild.hxx>
+#include <vcl/salbtype.hxx>
+#ifdef GSTREAMER
+#include <vcl/sysdata.hxx>
+#endif
+
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+#include <avmedia/mediawindow.hxx>
+
+#include <com/sun/star/media/XManager.hpp>
+#include <com/sun/star/media/XPlayer.hpp>
+#include <com/sun/star/media/XPlayerWindow.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/lang/XComponent.hdl>
+
+#include "viewmediashape.hxx"
+#include "mediashape.hxx"
+#include "tools.hxx"
+#include "unoview.hxx"
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ViewMediaShape::ViewMediaShape( const ViewLayerSharedPtr& rViewLayer,
+ const uno::Reference< drawing::XShape >& rxShape,
+ const uno::Reference< uno::XComponentContext >& rxContext ) :
+ mpViewLayer( rViewLayer ),
+ mpMediaWindow(),
+ maWindowOffset( 0, 0 ),
+ maBounds(),
+ mxShape( rxShape ),
+ mxPlayer(),
+ mxPlayerWindow(),
+ mxComponentContext( rxContext ),
+ mbIsSoundEnabled(true)
+ {
+ ENSURE_OR_THROW( mxShape.is(), "ViewMediaShape::ViewMediaShape(): Invalid Shape" );
+ ENSURE_OR_THROW( mpViewLayer, "ViewMediaShape::ViewMediaShape(): Invalid View" );
+ ENSURE_OR_THROW( mpViewLayer->getCanvas(), "ViewMediaShape::ViewMediaShape(): Invalid ViewLayer canvas" );
+ ENSURE_OR_THROW( mxComponentContext.is(), "ViewMediaShape::ViewMediaShape(): Invalid component context" );
+
+ UnoViewSharedPtr pUnoView (::boost::dynamic_pointer_cast<UnoView>(rViewLayer));
+ if (pUnoView)
+ {
+ mbIsSoundEnabled = pUnoView->isSoundEnabled();
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ ViewMediaShape::~ViewMediaShape()
+ {
+ try
+ {
+ endMedia();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ ViewLayerSharedPtr ViewMediaShape::getViewLayer() const
+ {
+ return mpViewLayer;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewMediaShape::startMedia()
+ {
+ if( !mxPlayer.is() )
+ implInitialize( maBounds );
+
+ if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) )
+ mxPlayer->start();
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ViewMediaShape::endMedia()
+ {
+ // shutdown player window
+ if( mxPlayerWindow.is() )
+ {
+ uno::Reference< lang::XComponent > xComponent( mxPlayerWindow, uno::UNO_QUERY );
+
+ if( xComponent.is() )
+ xComponent->dispose();
+
+ mxPlayerWindow.clear();
+ }
+
+#ifdef GSTREAMER
+ mpMediaWindow = ::std::auto_ptr< SystemChildWindow >();
+#else
+ mpMediaWindow = ::std::auto_ptr< JavaChildWindow >();
+#endif
+
+ // shutdown player
+ if( mxPlayer.is() )
+ {
+ mxPlayer->stop();
+
+ uno::Reference< lang::XComponent > xComponent( mxPlayer, uno::UNO_QUERY );
+
+ if( xComponent.is() )
+ xComponent->dispose();
+
+ mxPlayer.clear();
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ViewMediaShape::pauseMedia()
+ {
+ if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) )
+ mxPlayer->stop();
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ViewMediaShape::setMediaTime(double fTime)
+ {
+ if( mxPlayer.is() && ( mxPlayer->getDuration() > 0.0 ) )
+ mxPlayer->setMediaTime(fTime);
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewMediaShape::render( const ::basegfx::B2DRectangle& rBounds ) const
+ {
+ ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();;
+
+ if( !pCanvas )
+ return false;
+
+ if( !mpMediaWindow.get() && !mxPlayerWindow.is() )
+ {
+ // fill the shape background with black
+ fillRect( pCanvas,
+ rBounds,
+ 0x000000FFU );
+ }
+
+ return true;
+ }
+
+ bool ViewMediaShape::resize( const ::basegfx::B2DRectangle& rNewBounds ) const
+ {
+ maBounds = rNewBounds;
+
+ ::cppcanvas::CanvasSharedPtr pCanvas = mpViewLayer->getCanvas();;
+
+ if( !pCanvas )
+ return false;
+
+ if( !mxPlayerWindow.is() )
+ return true;
+
+ uno::Reference< beans::XPropertySet > xPropSet( pCanvas->getUNOCanvas()->getDevice(),
+ uno::UNO_QUERY );
+
+ uno::Reference< awt::XWindow > xParentWindow;
+ if( xPropSet.is() &&
+ getPropertyValue( xParentWindow,
+ xPropSet,
+ ::rtl::OUString::createFromAscii( "Window" )) )
+ {
+ const awt::Rectangle aRect( xParentWindow->getPosSize() );
+
+ maWindowOffset.X = aRect.X;
+ maWindowOffset.Y = aRect.Y;
+ }
+
+ ::basegfx::B2DRange aTmpRange;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRange,
+ rNewBounds,
+ mpViewLayer->getTransformation() );
+ const ::basegfx::B2IRange& rRangePix(
+ ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
+
+ mxPlayerWindow->setEnable( !rRangePix.isEmpty() );
+
+ if( rRangePix.isEmpty() )
+ return true;
+
+ const Point aPosPixel( rRangePix.getMinX() + maWindowOffset.X,
+ rRangePix.getMinY() + maWindowOffset.Y );
+ const Size aSizePixel( rRangePix.getMaxX() - rRangePix.getMinX(),
+ rRangePix.getMaxY() - rRangePix.getMinY() );
+
+ if( mpMediaWindow.get() )
+ {
+ mpMediaWindow->SetPosSizePixel( aPosPixel, aSizePixel );
+ mxPlayerWindow->setPosSize( 0, 0,
+ aSizePixel.Width(), aSizePixel.Height(),
+ 0 );
+ }
+ else
+ {
+ mxPlayerWindow->setPosSize( aPosPixel.X(), aPosPixel.Y(),
+ aSizePixel.Width(), aSizePixel.Height(),
+ 0 );
+ }
+
+ return true;
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewMediaShape::implInitialize( const ::basegfx::B2DRectangle& rBounds )
+ {
+ if( !mxPlayer.is() && mxShape.is() )
+ {
+ ENSURE_OR_RETURN_FALSE( mpViewLayer->getCanvas(),
+ "ViewMediaShape::update(): Invalid layer canvas" );
+
+ uno::Reference< rendering::XCanvas > xCanvas( mpViewLayer->getCanvas()->getUNOCanvas() );
+
+ if( xCanvas.is() )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet;
+ ::rtl::OUString aURL;
+
+ try
+ {
+ xPropSet.set( mxShape, uno::UNO_QUERY );
+
+ // create Player
+ if( xPropSet.is() &&
+ ( xPropSet->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaURL" ) ) ) >>=aURL ) )
+ {
+ implInitializeMediaPlayer( aURL );
+ }
+
+ // create visible object
+ uno::Sequence< uno::Any > aDeviceParams;
+
+ if( ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams ).getLength() > 1 )
+ {
+ ::rtl::OUString aImplName;
+
+ aDeviceParams[ 0 ] >>= aImplName;
+
+ if( aImplName.endsWithIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("VCL") ) || aImplName.endsWithIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("Cairo") ) )
+ {
+ implInitializeVCLBasedPlayerWindow( rBounds, aDeviceParams );
+ }
+ else if( aImplName.endsWithIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("DX")) ||
+ aImplName.endsWithIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("DX9")))
+ {
+ implInitializeDXBasedPlayerWindow( rBounds, aDeviceParams );
+ }
+ }
+
+ // set player properties
+ implSetMediaProperties( xPropSet );
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ }
+
+ return mxPlayer.is() || mxPlayerWindow.is();
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ViewMediaShape::implSetMediaProperties( const uno::Reference< beans::XPropertySet >& rxProps )
+ {
+ if( mxPlayer.is() )
+ {
+ mxPlayer->setMediaTime( 0.0 );
+
+ if( rxProps.is() )
+ {
+ sal_Bool bLoop( false );
+ getPropertyValue( bLoop,
+ rxProps,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Loop" )));
+ mxPlayer->setPlaybackLoop( bLoop );
+
+ sal_Bool bMute( false );
+ getPropertyValue( bMute,
+ rxProps,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Mute" )));
+ mxPlayer->setMute( bMute || !mbIsSoundEnabled);
+
+ sal_Int16 nVolumeDB(0);
+ getPropertyValue( nVolumeDB,
+ rxProps,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VolumeDB" )));
+ mxPlayer->setVolumeDB( nVolumeDB );
+
+ if( mxPlayerWindow.is() )
+ {
+ media::ZoomLevel eZoom(media::ZoomLevel_FIT_TO_WINDOW);
+ getPropertyValue( eZoom,
+ rxProps,
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Zoom" )));
+ mxPlayerWindow->setZoomLevel( eZoom );
+ }
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ void ViewMediaShape::implInitializeMediaPlayer( const ::rtl::OUString& rMediaURL )
+ {
+ if( !mxPlayer.is() )
+ {
+ try
+ {
+ if( rMediaURL.getLength() )
+ {
+ mxPlayer.set( avmedia::MediaWindow::createPlayer( rMediaURL ),
+ uno::UNO_QUERY );
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( const uno::Exception& )
+ {
+ throw lang::NoSupportException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "No video support for ") ) + rMediaURL,
+ uno::Reference<uno::XInterface>() );
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewMediaShape::implInitializeVCLBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds,
+ const uno::Sequence< uno::Any >& rVCLDeviceParams)
+ {
+ OSL_TRACE( "ViewMediaShape::implInitializeVCLBasedPlayerWindow" );
+ if( !mpMediaWindow.get() && !rBounds.isEmpty() )
+ {
+ try
+ {
+ sal_Int64 aVal=0;
+
+ rVCLDeviceParams[ 1 ] >>= aVal;
+
+ Window* pWindow = reinterpret_cast< Window* >( aVal );
+
+ if( pWindow )
+ {
+ ::basegfx::B2DRange aTmpRange;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRange,
+ rBounds,
+ mpViewLayer->getTransformation() );
+ const ::basegfx::B2IRange& rRangePix(
+ ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
+
+ if( !rRangePix.isEmpty() )
+ {
+ uno::Sequence< uno::Any > aArgs( 3 );
+ awt::Rectangle aAWTRect( rRangePix.getMinX(),
+ rRangePix.getMinY(),
+ rRangePix.getMaxX() - rRangePix.getMinX(),
+ rRangePix.getMaxY() - rRangePix.getMinY() );
+
+#ifdef GSTREAMER
+ OSL_TRACE( "created sys child window for viewmediashape" );
+ mpMediaWindow = ::std::auto_ptr< SystemChildWindow >( new SystemChildWindow( pWindow, WB_CLIPCHILDREN ) );
+#else
+ mpMediaWindow = ::std::auto_ptr< JavaChildWindow >( new JavaChildWindow( pWindow, WB_CLIPCHILDREN ) );
+#endif
+ mpMediaWindow->SetBackground( Color( COL_BLACK ) );
+ mpMediaWindow->SetPosSizePixel( Point( aAWTRect.X,
+ aAWTRect.Y ),
+ Size( aAWTRect.Width,
+ aAWTRect.Height ));
+ mpMediaWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ mpMediaWindow->EnableEraseBackground( FALSE );
+ mpMediaWindow->EnablePaint( FALSE );
+ mpMediaWindow->SetForwardKey( TRUE );
+ mpMediaWindow->SetMouseTransparent( TRUE );
+ mpMediaWindow->Show();
+
+ if( mxPlayer.is() )
+ {
+#ifndef GSTREAMER
+ aArgs[ 0 ] = uno::makeAny(
+ sal::static_int_cast<sal_IntPtr>(
+ mpMediaWindow->getParentWindowHandleForJava()) );
+#else
+ aArgs[ 0 ] = uno::makeAny ( (sal_Int32) 0 );
+#endif
+ aAWTRect.X = aAWTRect.Y = 0;
+ aArgs[ 1 ] = uno::makeAny( aAWTRect );
+#ifdef GSTREAMER
+ const SystemEnvData *pSystemData = mpMediaWindow->GetSystemData();
+ OSL_TRACE( "xwindow id: %ld", pSystemData->aWindow );
+ aArgs[ 2 ] = uno::makeAny( pSystemData->aWindow );
+#endif
+
+ mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) );
+
+ if( mxPlayerWindow.is() )
+ {
+ mxPlayerWindow->setVisible( true );
+ mxPlayerWindow->setEnable( true );
+ }
+ }
+ }
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ return mxPlayerWindow.is();
+ }
+
+ // ---------------------------------------------------------------------
+
+ bool ViewMediaShape::implInitializeDXBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds,
+ const uno::Sequence< uno::Any >& rDXDeviceParams )
+ {
+ if( !mxPlayerWindow.is() )
+ {
+ try
+ {
+ if( rDXDeviceParams.getLength() == 2 )
+ {
+ sal_Int64 aWNDVal=0;
+
+ rDXDeviceParams[ 1 ] >>= aWNDVal;
+
+ if( aWNDVal )
+ {
+ ::basegfx::B2DRange aTmpRange;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRange,
+ rBounds,
+ mpViewLayer->getTransformation() );
+ const ::basegfx::B2IRange& rRangePix(
+ ::basegfx::unotools::b2ISurroundingRangeFromB2DRange( aTmpRange ));
+
+ if( !rRangePix.isEmpty() )
+ {
+ uno::Sequence< uno::Any > aArgs( 2 );
+ awt::Rectangle aAWTRect( rRangePix.getMinX() + maWindowOffset.X,
+ rRangePix.getMinY() + maWindowOffset.Y,
+ rRangePix.getMaxX() - rRangePix.getMinX(),
+ rRangePix.getMaxY() - rRangePix.getMinY() );
+
+ if( mxPlayer.is() )
+ {
+ aArgs[ 0 ] = uno::makeAny(
+ sal::static_int_cast<sal_Int32>(
+ aWNDVal) );
+ aArgs[ 1 ] = uno::makeAny( aAWTRect );
+
+ mxPlayerWindow.set( mxPlayer->createPlayerWindow( aArgs ) );
+ }
+ }
+ }
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ return mxPlayerWindow.is();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewmediashape.hxx b/slideshow/source/engine/shapes/viewmediashape.hxx
new file mode 100644
index 000000000000..576688891cf7
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewmediashape.hxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWMEDIASHAPE_HXX
+#define INCLUDED_SLIDESHOW_VIEWMEDIASHAPE_HXX
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <com/sun/star/awt/Point.hpp>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include "viewlayer.hxx"
+
+class JavaChildWindow;
+class SystemChildWindow;
+
+namespace com { namespace sun { namespace star { namespace drawing {
+ class XShape;
+}
+namespace media {
+ class XPlayer;
+ class XPlayerWindow;
+}
+namespace uno {
+ class XComponentContext;
+}
+namespace beans{
+ class XPropertySet;
+} } } }
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class is the viewable representation of a draw
+ document's media object, associated to a specific View
+
+ The class is able to render the associated media shape on
+ View implementations.
+ */
+ class ViewMediaShape : private boost::noncopyable
+ {
+ public:
+ /** Create a ViewMediaShape for the given View
+
+ @param rView
+ The associated View object.
+ */
+ ViewMediaShape( const ViewLayerSharedPtr& rViewLayer,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& rxShape,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& rxContext );
+
+ /** destroy the object
+ */
+ virtual ~ViewMediaShape();
+
+ /** Query the associated view layer of this shape
+ */
+ ViewLayerSharedPtr getViewLayer() const;
+
+ // animation methods
+ //------------------------------------------------------------------
+
+ /** Notify the ViewShape that an animation starts now
+
+ This method enters animation mode on the associate
+ target view. The shape can be animated in parallel on
+ different views.
+
+ @return whether the mode change finished successfully.
+ */
+ bool startMedia();
+
+ /** Notify the ViewShape that it is no longer animated
+
+ This methods ends animation mode on the associate
+ target view
+ */
+ void endMedia();
+
+ /** Notify the ViewShape that it should pause playback
+
+ This methods pauses animation on the associate
+ target view. The content stays visible (for video)
+ */
+ void pauseMedia();
+
+ /** Set current time of media.
+
+ @param fTime
+ Local media time that should now be presented, in seconds.
+ */
+ void setMediaTime(double fTime);
+
+ // render methods
+ //------------------------------------------------------------------
+
+ /** Render the ViewShape
+
+ This method renders the ViewMediaShape on the associated view.
+
+ @param rBounds
+ The current media shape bounds
+
+ @return whether the rendering finished successfully.
+ */
+ bool render( const ::basegfx::B2DRectangle& rBounds ) const;
+
+ /** Resize the ViewShape
+
+ This method updates the ViewMediaShape size on the
+ associated view. It does not render.
+
+ @param rBounds
+ The current media shape bounds
+
+ @return whether the resize finished successfully.
+ */
+ bool resize( const ::basegfx::B2DRectangle& rNewBounds ) const;
+
+ private:
+
+ bool implInitialize( const ::basegfx::B2DRectangle& rBounds );
+ void implSetMediaProperties( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rxProps );
+ void implInitializeMediaPlayer( const ::rtl::OUString& rMediaURL );
+ bool implInitializeVCLBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rVCLDeviceParams );
+ bool implInitializeDXBasedPlayerWindow( const ::basegfx::B2DRectangle& rBounds,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rDXDeviceParams );
+
+ ViewLayerSharedPtr mpViewLayer;
+#ifdef GSTREAMER
+ ::std::auto_ptr< SystemChildWindow > mpMediaWindow;
+#else
+ ::std::auto_ptr< JavaChildWindow > mpMediaWindow;
+#endif
+ mutable ::com::sun::star::awt::Point maWindowOffset;
+ mutable ::basegfx::B2DRectangle maBounds;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > mxShape;
+ ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayer > mxPlayer;
+ ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayerWindow > mxPlayerWindow;
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> mxComponentContext;
+ bool mbIsSoundEnabled;
+ };
+
+ typedef ::boost::shared_ptr< ViewMediaShape > ViewMediaShapeSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWMEDIASHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewshape.cxx b/slideshow/source/engine/shapes/viewshape.cxx
new file mode 100644
index 000000000000..319344f4f083
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewshape.cxx
@@ -0,0 +1,901 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <math.h>
+
+#include <rtl/logfile.hxx>
+#include <rtl/math.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/PanoseLetterForm.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <comphelper/anytostring.hxx>
+
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <canvas/verbosetrace.hxx>
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include "viewshape.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ // TODO(F2): Provide sensible setup for mtf-related attributes (fill mode,
+ // char rotation etc.). Do that via mtf argument at this object
+
+ bool ViewShape::prefetch( RendererCacheEntry& io_rCacheEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ShapeAttributeLayerSharedPtr& rAttr ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::prefetch()" );
+ ENSURE_OR_RETURN_FALSE( rMtf,
+ "ViewShape::prefetch(): no valid metafile!" );
+
+ if( rMtf != io_rCacheEntry.mpMtf ||
+ rDestinationCanvas != io_rCacheEntry.getDestinationCanvas() )
+ {
+ // buffered renderer invalid, re-create
+ ::cppcanvas::Renderer::Parameters aParms;
+
+ // rendering attribute override parameter struct. For
+ // every valid attribute, the corresponding struct
+ // member is filled, which in the metafile renderer
+ // forces rendering with the given attribute.
+ if( rAttr )
+ {
+ if( rAttr->isFillColorValid() )
+ {
+ // convert RGBColor to RGBA32 integer. Note
+ // that getIntegerColor() also truncates
+ // out-of-range values appropriately
+ aParms.maFillColor =
+ rAttr->getFillColor().getIntegerColor();
+ }
+ if( rAttr->isLineColorValid() )
+ {
+ // convert RGBColor to RGBA32 integer. Note
+ // that getIntegerColor() also truncates
+ // out-of-range values appropriately
+ aParms.maLineColor =
+ rAttr->getLineColor().getIntegerColor();
+ }
+ if( rAttr->isCharColorValid() )
+ {
+ // convert RGBColor to RGBA32 integer. Note
+ // that getIntegerColor() also truncates
+ // out-of-range values appropriately
+ aParms.maTextColor =
+ rAttr->getCharColor().getIntegerColor();
+ }
+ if( rAttr->isDimColorValid() )
+ {
+ // convert RGBColor to RGBA32 integer. Note
+ // that getIntegerColor() also truncates
+ // out-of-range values appropriately
+
+ // dim color overrides all other colors
+ aParms.maFillColor =
+ aParms.maLineColor =
+ aParms.maTextColor =
+ rAttr->getDimColor().getIntegerColor();
+ }
+ if( rAttr->isFontFamilyValid() )
+ {
+ aParms.maFontName =
+ rAttr->getFontFamily();
+ }
+ if( rAttr->isCharScaleValid() )
+ {
+ ::basegfx::B2DHomMatrix aMatrix;
+
+ // enlarge text by given scale factor. Do that
+ // with the middle of the shape as the center
+ // of scaling.
+ aMatrix.translate( -0.5, -0.5 );
+ aMatrix.scale( rAttr->getCharScale(),
+ rAttr->getCharScale() );
+ aMatrix.translate( 0.5, 0.5 );
+
+ aParms.maTextTransformation = aMatrix;
+ }
+ if( rAttr->isCharWeightValid() )
+ {
+ aParms.maFontWeight =
+ static_cast< sal_Int8 >(
+ ::basegfx::fround(
+ ::std::max( 0.0,
+ ::std::min( 11.0,
+ rAttr->getCharWeight() / 20.0 ) ) ) );
+ }
+ if( rAttr->isCharPostureValid() )
+ {
+ aParms.maFontLetterForm =
+ rAttr->getCharPosture() == awt::FontSlant_NONE ?
+ rendering::PanoseLetterForm::ANYTHING :
+ rendering::PanoseLetterForm::OBLIQUE_CONTACT;
+ }
+ if( rAttr->isUnderlineModeValid() )
+ {
+ aParms.maFontUnderline =
+ rAttr->getUnderlineMode();
+ }
+ }
+
+ io_rCacheEntry.mpRenderer = ::cppcanvas::VCLFactory::getInstance().createRenderer( rDestinationCanvas,
+ *rMtf.get(),
+ aParms );
+
+ io_rCacheEntry.mpMtf = rMtf;
+ io_rCacheEntry.mpDestinationCanvas = rDestinationCanvas;
+
+ // also invalidate alpha compositing bitmap (created
+ // new renderer, which possibly generates different
+ // output). Do NOT invalidate, if we're incidentally
+ // rendering INTO it.
+ if( rDestinationCanvas != io_rCacheEntry.mpLastBitmapCanvas )
+ {
+ io_rCacheEntry.mpLastBitmapCanvas.reset();
+ io_rCacheEntry.mpLastBitmap.reset();
+ }
+ }
+
+ return io_rCacheEntry.mpRenderer;
+ }
+
+ bool ViewShape::draw( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ShapeAttributeLayerSharedPtr& rAttr,
+ const ::basegfx::B2DHomMatrix& rTransform,
+ const ::basegfx::B2DPolyPolygon* pClip,
+ const VectorOfDocTreeNodes& rSubsets ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::draw()" );
+
+ ::cppcanvas::RendererSharedPtr pRenderer(
+ getRenderer( rDestinationCanvas, rMtf, rAttr ) );
+
+ ENSURE_OR_RETURN_FALSE( pRenderer, "ViewShape::draw(): Invalid renderer" );
+
+ pRenderer->setTransformation( rTransform );
+#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
+ rendering::RenderState aRenderState;
+ ::canvas::tools::initRenderState(aRenderState);
+ ::canvas::tools::setRenderStateTransform(aRenderState,
+ rTransform);
+ aRenderState.DeviceColor.realloc(4);
+ aRenderState.DeviceColor[0] = 1.0;
+ aRenderState.DeviceColor[1] = 0.0;
+ aRenderState.DeviceColor[2] = 0.0;
+ aRenderState.DeviceColor[3] = 1.0;
+
+ try
+ {
+ rDestinationCanvas->getUNOCanvas()->drawLine( geometry::RealPoint2D(0.0,0.0),
+ geometry::RealPoint2D(1.0,1.0),
+ rDestinationCanvas->getViewState(),
+ aRenderState );
+ rDestinationCanvas->getUNOCanvas()->drawLine( geometry::RealPoint2D(1.0,0.0),
+ geometry::RealPoint2D(0.0,1.0),
+ rDestinationCanvas->getViewState(),
+ aRenderState );
+ }
+ catch( uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+#endif
+ if( pClip )
+ pRenderer->setClip( *pClip );
+ else
+ pRenderer->setClip();
+
+ if( rSubsets.empty() )
+ {
+ return pRenderer->draw();
+ }
+ else
+ {
+ // render subsets of whole metafile
+ // --------------------------------
+
+ bool bRet(true);
+ VectorOfDocTreeNodes::const_iterator aIter( rSubsets.begin() );
+ const VectorOfDocTreeNodes::const_iterator aEnd ( rSubsets.end() );
+ while( aIter != aEnd )
+ {
+ if( !pRenderer->drawSubset( aIter->getStartIndex(),
+ aIter->getEndIndex() ) )
+ bRet = false;
+
+ ++aIter;
+ }
+
+ return bRet;
+ }
+ }
+
+ namespace
+ {
+ /// Convert untransformed shape update area to device pixel.
+ ::basegfx::B2DRectangle shapeArea2AreaPixel( const ::basegfx::B2DHomMatrix& rCanvasTransformation,
+ const ::basegfx::B2DRectangle& rUntransformedArea )
+ {
+ // convert area to pixel, and add anti-aliasing border
+
+ // TODO(P1): Should the view transform some
+ // day contain rotation/shear, transforming
+ // the original bounds with the total
+ // transformation might result in smaller
+ // overall bounds.
+
+ ::basegfx::B2DRectangle aBoundsPixel;
+ ::canvas::tools::calcTransformedRectBounds( aBoundsPixel,
+ rUntransformedArea,
+ rCanvasTransformation );
+
+ // add antialiasing border around the shape (AA
+ // touches pixel _outside_ the nominal bound rect)
+ aBoundsPixel.grow( ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE );
+
+ return aBoundsPixel;
+ }
+
+ /// Convert shape unit rect to device pixel.
+ ::basegfx::B2DRectangle calcUpdateAreaPixel( const ::basegfx::B2DRectangle& rUnitBounds,
+ const ::basegfx::B2DHomMatrix& rShapeTransformation,
+ const ::basegfx::B2DHomMatrix& rCanvasTransformation,
+ const ShapeAttributeLayerSharedPtr& pAttr )
+ {
+ // calc update area for whole shape (including
+ // character scaling)
+ return shapeArea2AreaPixel( rCanvasTransformation,
+ getShapeUpdateArea( rUnitBounds,
+ rShapeTransformation,
+ pAttr ) );
+ }
+ }
+
+ bool ViewShape::renderSprite( const ViewLayerSharedPtr& rViewLayer,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ::basegfx::B2DRectangle& rOrigBounds,
+ const ::basegfx::B2DRectangle& rBounds,
+ const ::basegfx::B2DRectangle& rUnitBounds,
+ int nUpdateFlags,
+ const ShapeAttributeLayerSharedPtr& pAttr,
+ const VectorOfDocTreeNodes& rSubsets,
+ double nPrio,
+ bool bIsVisible ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::renderSprite()" );
+
+ // TODO(P1): For multiple views, it might pay off to reorg Shape and ViewShape,
+ // in that all the common setup steps here are refactored to Shape (would then
+ // have to be performed only _once_ per Shape paint).
+
+ if( !bIsVisible ||
+ rUnitBounds.isEmpty() ||
+ rOrigBounds.isEmpty() ||
+ rBounds.isEmpty() )
+ {
+ // shape is invisible or has zero size, no need to
+ // update anything.
+ if( mpSprite )
+ mpSprite->hide();
+
+ return true;
+ }
+
+
+ // calc sprite position, size and content transformation
+ // =====================================================
+
+ // the shape transformation for a sprite is always a
+ // simple scale-up to the nominal shape size. Everything
+ // else is handled via the sprite transformation
+ ::basegfx::B2DHomMatrix aNonTranslationalShapeTransformation;
+ aNonTranslationalShapeTransformation.scale( rOrigBounds.getWidth(),
+ rOrigBounds.getHeight() );
+ ::basegfx::B2DHomMatrix aShapeTransformation( aNonTranslationalShapeTransformation );
+ aShapeTransformation.translate( rOrigBounds.getMinX(),
+ rOrigBounds.getMinY() );
+
+ const ::basegfx::B2DHomMatrix& rCanvasTransform(
+ rViewLayer->getSpriteTransformation() );
+
+ // area actually needed for the sprite
+ const ::basegfx::B2DRectangle& rSpriteBoundsPixel(
+ calcUpdateAreaPixel( rUnitBounds,
+ aShapeTransformation,
+ rCanvasTransform,
+ pAttr ) );
+
+ // actual area for the shape (without subsetting, but
+ // including char scaling)
+ const ::basegfx::B2DRectangle& rShapeBoundsPixel(
+ calcUpdateAreaPixel( ::basegfx::B2DRectangle(0.0,0.0,1.0,1.0),
+ aShapeTransformation,
+ rCanvasTransform,
+ pAttr ) );
+
+ // nominal area for the shape (without subsetting, without
+ // char scaling). NOTE: to cancel the shape translation,
+ // contained in rSpriteBoundsPixel, this is _without_ any
+ // translational component (fixed along with #121921#).
+ ::basegfx::B2DRectangle aLogShapeBounds;
+ const ::basegfx::B2DRectangle& rNominalShapeBoundsPixel(
+ shapeArea2AreaPixel( rCanvasTransform,
+ ::canvas::tools::calcTransformedRectBounds(
+ aLogShapeBounds,
+ ::basegfx::B2DRectangle(0.0,0.0,1.0,1.0),
+ aNonTranslationalShapeTransformation ) ) );
+
+ // create (or resize) sprite with sprite's pixel size, if
+ // not done already
+ const ::basegfx::B2DSize& rSpriteSizePixel(rSpriteBoundsPixel.getRange());
+ if( !mpSprite )
+ {
+ mpSprite.reset(
+ new AnimatedSprite( mpViewLayer,
+ rSpriteSizePixel,
+ nPrio ));
+ }
+ else
+ {
+ // TODO(F2): when the sprite _actually_ gets resized,
+ // content needs a repaint!
+ mpSprite->resize( rSpriteSizePixel );
+ }
+
+ ENSURE_OR_RETURN_FALSE( mpSprite, "ViewShape::renderSprite(): No sprite" );
+
+ VERBOSE_TRACE( "ViewShape::renderSprite(): Rendering sprite 0x%X",
+ mpSprite.get() );
+
+
+ // always show the sprite (might have been hidden before)
+ mpSprite->show();
+
+ // determine center of sprite output position in pixel
+ // (assumption here: all shape transformations have the
+ // shape center as the pivot point). From that, subtract
+ // distance of rSpriteBoundsPixel's left, top edge from
+ // rShapeBoundsPixel's center. This moves the sprite at
+ // the appropriate output position within the virtual
+ // rShapeBoundsPixel area.
+ ::basegfx::B2DPoint aSpritePosPixel( rBounds.getCenter() );
+ aSpritePosPixel *= rCanvasTransform;
+ aSpritePosPixel -= rShapeBoundsPixel.getCenter() - rSpriteBoundsPixel.getMinimum();
+
+ // the difference between rShapeBoundsPixel and
+ // rSpriteBoundsPixel upper, left corner is: the offset we
+ // have to move sprite output to the right, top (to make
+ // the desired subset content visible at all)
+ const ::basegfx::B2DSize& rSpriteCorrectionOffset(
+ rSpriteBoundsPixel.getMinimum() - rNominalShapeBoundsPixel.getMinimum() );
+
+ // offset added top, left for anti-aliasing (otherwise,
+ // shapes fully filling the sprite will have anti-aliased
+ // pixel cut off)
+ const ::basegfx::B2DSize aAAOffset(
+ ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE,
+ ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE );
+
+ // set pixel output offset to sprite: we always leave
+ // ANTIALIASING_EXTRA_SIZE room atop and to the left, and,
+ // what's more, for subsetted shapes, we _have_ to cancel
+ // the effect of the shape renderer outputting the subset
+ // at its absolute position inside the shape, instead of
+ // at the origin.
+ // NOTE: As for now, sprites are always positioned on
+ // integer pixel positions on screen, have to round to
+ // nearest integer here, too (fixed along with #121921#)
+ mpSprite->setPixelOffset(
+ aAAOffset - ::basegfx::B2DSize(
+ ::basegfx::fround( rSpriteCorrectionOffset.getX() ),
+ ::basegfx::fround( rSpriteCorrectionOffset.getY() ) ) );
+
+ // always set sprite position and transformation, since
+ // they do not relate directly to the update flags
+ // (e.g. sprite position changes when sprite size changes)
+ mpSprite->movePixel( aSpritePosPixel );
+ mpSprite->transform( getSpriteTransformation( rSpriteSizePixel,
+ rOrigBounds.getRange(),
+ pAttr ) );
+
+
+ // process flags
+ // =============
+
+ bool bRedrawRequired( mbForceUpdate || (nUpdateFlags & FORCE) );
+
+ if( mbForceUpdate || (nUpdateFlags & ALPHA) )
+ {
+ mpSprite->setAlpha( (pAttr && pAttr->isAlphaValid()) ?
+ ::basegfx::clamp(pAttr->getAlpha(),
+ 0.0,
+ 1.0) :
+ 1.0 );
+ }
+ if( mbForceUpdate || (nUpdateFlags & CLIP) )
+ {
+ if( pAttr && pAttr->isClipValid() )
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly( pAttr->getClip() );
+
+ // extract linear part of canvas view transformation
+ // (linear means: without translational components)
+ ::basegfx::B2DHomMatrix aViewTransform(
+ mpViewLayer->getTransformation() );
+ aViewTransform.set( 0, 2, 0.0 );
+ aViewTransform.set( 1, 2, 0.0 );
+
+ // make the clip 2*ANTIALIASING_EXTRA_SIZE larger
+ // such that it's again centered over the sprite.
+ aViewTransform.scale(rSpriteSizePixel.getX()/
+ (rSpriteSizePixel.getX()-2*::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE),
+ rSpriteSizePixel.getY()/
+ (rSpriteSizePixel.getY()-2*::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE));
+
+ // transform clip polygon from view to device
+ // coordinate space
+ aClipPoly.transform( aViewTransform );
+
+ mpSprite->clip( aClipPoly );
+ }
+ else
+ mpSprite->clip();
+ }
+ if( mbForceUpdate || (nUpdateFlags & CONTENT) )
+ {
+ bRedrawRequired = true;
+
+ // TODO(P1): maybe provide some appearance change methods at
+ // the Renderer interface
+
+ // force the renderer to be regenerated below, for the
+ // different attributes to take effect
+ invalidateRenderer();
+ }
+
+ mbForceUpdate = false;
+
+ if( !bRedrawRequired )
+ return true;
+
+
+ // sprite needs repaint - output to sprite canvas
+ // ==============================================
+
+ ::cppcanvas::CanvasSharedPtr pContentCanvas( mpSprite->getContentCanvas() );
+
+ return draw( pContentCanvas,
+ rMtf,
+ pAttr,
+ aShapeTransformation,
+ NULL, // clipping is done via Sprite::clip()
+ rSubsets );
+ }
+
+ bool ViewShape::render( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ::basegfx::B2DRectangle& rBounds,
+ const ::basegfx::B2DRectangle& rUpdateBounds,
+ int nUpdateFlags,
+ const ShapeAttributeLayerSharedPtr& pAttr,
+ const VectorOfDocTreeNodes& rSubsets,
+ bool bIsVisible ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::render()" );
+
+ // TODO(P1): For multiple views, it might pay off to reorg Shape and ViewShape,
+ // in that all the common setup steps here are refactored to Shape (would then
+ // have to be performed only _once_ per Shape paint).
+
+ if( !bIsVisible )
+ {
+ VERBOSE_TRACE( "ViewShape::render(): skipping shape %X", this );
+
+ // shape is invisible, no need to update anything.
+ return true;
+ }
+
+ // since we have no sprite here, _any_ update request
+ // translates into a required redraw.
+ bool bRedrawRequired( mbForceUpdate || nUpdateFlags != 0 );
+
+ if( (nUpdateFlags & CONTENT) )
+ {
+ // TODO(P1): maybe provide some appearance change methods at
+ // the Renderer interface
+
+ // force the renderer to be regenerated below, for the
+ // different attributes to take effect
+ invalidateRenderer();
+ }
+
+ mbForceUpdate = false;
+
+ if( !bRedrawRequired )
+ return true;
+
+ VERBOSE_TRACE( "ViewShape::render(): rendering shape %X at position (%f,%f)",
+ this,
+ rBounds.getMinX(),
+ rBounds.getMinY() );
+
+
+ // shape needs repaint - setup all that's needed
+ // ---------------------------------------------
+
+ boost::optional<basegfx::B2DPolyPolygon> aClip;
+
+ if( pAttr )
+ {
+ // setup clip poly
+ if( pAttr->isClipValid() )
+ aClip.reset( pAttr->getClip() );
+
+ // emulate global shape alpha by first rendering into
+ // a temp bitmap, and then to screen (this would have
+ // been much easier if we'd be currently a sprite -
+ // see above)
+ if( pAttr->isAlphaValid() )
+ {
+ const double nAlpha( pAttr->getAlpha() );
+
+ if( !::basegfx::fTools::equalZero( nAlpha ) &&
+ !::rtl::math::approxEqual(nAlpha, 1.0) )
+ {
+ // render with global alpha - have to prepare
+ // a bitmap, and render that with modulated
+ // alpha
+ // -------------------------------------------
+
+ const ::basegfx::B2DHomMatrix aTransform(
+ getShapeTransformation( rBounds,
+ pAttr ) );
+
+ // TODO(P1): Should the view transform some
+ // day contain rotation/shear, transforming
+ // the original bounds with the total
+ // transformation might result in smaller
+ // overall bounds.
+
+ // determine output rect of _shape update
+ // area_ in device pixel
+ const ::basegfx::B2DHomMatrix aCanvasTransform(
+ rDestinationCanvas->getTransformation() );
+ ::basegfx::B2DRectangle aTmpRect;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRect,
+ rUpdateBounds,
+ aCanvasTransform );
+
+ // pixel size of cache bitmap: round up to
+ // nearest int
+ const ::basegfx::B2ISize aBmpSize( static_cast<sal_Int32>( aTmpRect.getWidth() )+1,
+ static_cast<sal_Int32>( aTmpRect.getHeight() )+1 );
+
+ // try to fetch temporary surface for alpha
+ // compositing (to achieve the global alpha
+ // blend effect, have to first render shape as
+ // a whole, then blit that surface with global
+ // alpha to the destination)
+ const RendererCacheVector::iterator aCompositingSurface(
+ getCacheEntry( rDestinationCanvas ) );
+
+ if( !aCompositingSurface->mpLastBitmapCanvas ||
+ aCompositingSurface->mpLastBitmapCanvas->getSize() != aBmpSize )
+ {
+ // create a bitmap of appropriate size
+ ::cppcanvas::BitmapSharedPtr pBitmap(
+ ::cppcanvas::BaseGfxFactory::getInstance().createAlphaBitmap(
+ rDestinationCanvas,
+ aBmpSize ) );
+
+ ENSURE_OR_THROW(pBitmap,
+ "ViewShape::render(): Could not create compositing surface");
+
+ aCompositingSurface->mpDestinationCanvas = rDestinationCanvas;
+ aCompositingSurface->mpLastBitmap = pBitmap;
+ aCompositingSurface->mpLastBitmapCanvas = pBitmap->getBitmapCanvas();
+ }
+
+ // buffer aCompositingSurface iterator content
+ // - said one might get invalidated during
+ // draw() below.
+ ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas(
+ aCompositingSurface->mpLastBitmapCanvas );
+
+ ::cppcanvas::BitmapSharedPtr pBitmap(
+ aCompositingSurface->mpLastBitmap);
+
+ // setup bitmap canvas transformation -
+ // which happens to be the destination
+ // canvas transformation without any
+ // translational components.
+ //
+ // But then, the render transformation as
+ // calculated by getShapeTransformation()
+ // above outputs the shape at its real
+ // destination position. Thus, we have to
+ // offset the output back to the origin,
+ // for which we simply plug in the
+ // negative position of the left, top edge
+ // of the shape's bound rect in device
+ // pixel into aLinearTransform below.
+ ::basegfx::B2DHomMatrix aAdjustedCanvasTransform( aCanvasTransform );
+ aAdjustedCanvasTransform.translate( -aTmpRect.getMinX(),
+ -aTmpRect.getMinY() );
+
+ pBitmapCanvas->setTransformation( aAdjustedCanvasTransform );
+
+ // TODO(P2): If no update flags, or only
+ // alpha_update is set, we can save us the
+ // rendering into the bitmap (uh, it's not
+ // _that_ easy - for a forced redraw,
+ // e.g. when ending an animation, we always
+ // get UPDATE_FORCE here).
+
+ // render into this bitmap
+ if( !draw( pBitmapCanvas,
+ rMtf,
+ pAttr,
+ aTransform,
+ !aClip ? NULL : &(*aClip),
+ rSubsets ) )
+ {
+ return false;
+ }
+
+ // render bitmap to screen, with given global
+ // alpha. Since the bitmap already contains
+ // pixel-equivalent output, we have to use the
+ // inverse view transformation, adjusted with
+ // the final shape output position (note:
+ // cannot simply change the view
+ // transformation here, as that would affect a
+ // possibly set clip!)
+ ::basegfx::B2DHomMatrix aBitmapTransform( aCanvasTransform );
+ OSL_ENSURE( aBitmapTransform.isInvertible(),
+ "ViewShape::render(): View transformation is singular!" );
+
+ aBitmapTransform.invert();
+
+ const basegfx::B2DHomMatrix aTranslation(basegfx::tools::createTranslateB2DHomMatrix(
+ aTmpRect.getMinX(), aTmpRect.getMinY()));
+
+ aBitmapTransform = aBitmapTransform * aTranslation;
+ pBitmap->setTransformation( aBitmapTransform );
+
+ // finally, render bitmap alpha-modulated
+ pBitmap->drawAlphaModulated( nAlpha );
+
+ return true;
+ }
+ }
+ }
+
+ // retrieve shape transformation, _with_ shape translation
+ // to actual page position.
+ const ::basegfx::B2DHomMatrix aTransform(
+ getShapeTransformation( rBounds,
+ pAttr ) );
+
+ return draw( rDestinationCanvas,
+ rMtf,
+ pAttr,
+ aTransform,
+ !aClip ? NULL : &(*aClip),
+ rSubsets );
+ }
+
+
+ // -------------------------------------------------------------------------------------
+
+ ViewShape::ViewShape( const ViewLayerSharedPtr& rViewLayer ) :
+ mpViewLayer( rViewLayer ),
+ maRenderers(),
+ mpSprite(),
+ mbAnimationMode( false ),
+ mbForceUpdate( true )
+ {
+ ENSURE_OR_THROW( mpViewLayer, "ViewShape::ViewShape(): Invalid View" );
+ }
+
+ ViewLayerSharedPtr ViewShape::getViewLayer() const
+ {
+ return mpViewLayer;
+ }
+
+ ViewShape::RendererCacheVector::iterator ViewShape::getCacheEntry( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas ) const
+ {
+ // lookup destination canvas - is there already a renderer
+ // created for that target?
+ RendererCacheVector::iterator aIter;
+ const RendererCacheVector::iterator aEnd( maRenderers.end() );
+
+ // already there?
+ if( (aIter=::std::find_if( maRenderers.begin(),
+ aEnd,
+ ::boost::bind(
+ ::std::equal_to< ::cppcanvas::CanvasSharedPtr >(),
+ ::boost::cref( rDestinationCanvas ),
+ ::boost::bind(
+ &RendererCacheEntry::getDestinationCanvas,
+ _1 ) ) ) ) == aEnd )
+ {
+ if( maRenderers.size() >= MAX_RENDER_CACHE_ENTRIES )
+ {
+ // cache size exceeded - prune entries. For now,
+ // simply remove the first one, which of course
+ // breaks for more complex access schemes. But in
+ // general, this leads to most recently used
+ // entries to reside at the end of the vector.
+ maRenderers.erase( maRenderers.begin() );
+
+ // ATTENTION: after this, both aIter and aEnd are
+ // invalid!
+ }
+
+ // not yet in cache - add default-constructed cache
+ // entry, to have something to return
+ maRenderers.push_back( RendererCacheEntry() );
+ aIter = maRenderers.end()-1;
+ }
+
+ return aIter;
+ }
+
+ ::cppcanvas::RendererSharedPtr ViewShape::getRenderer( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ShapeAttributeLayerSharedPtr& rAttr ) const
+ {
+ // lookup destination canvas - is there already a renderer
+ // created for that target?
+ const RendererCacheVector::iterator aIter(
+ getCacheEntry( rDestinationCanvas ) );
+
+ // now we have a valid entry, either way. call prefetch()
+ // on it, nevertheless - maybe the metafile changed, and
+ // the renderer still needs an update (prefetch() will
+ // detect that)
+ if( prefetch( *aIter,
+ rDestinationCanvas,
+ rMtf,
+ rAttr ) )
+ {
+ return aIter->mpRenderer;
+ }
+ else
+ {
+ // prefetch failed - renderer is invalid
+ return ::cppcanvas::RendererSharedPtr();
+ }
+ }
+
+ void ViewShape::invalidateRenderer() const
+ {
+ // simply clear the cache. Subsequent getRenderer() calls
+ // will regenerate the Renderers.
+ maRenderers.clear();
+ }
+
+ ::basegfx::B2DSize ViewShape::getAntialiasingBorder() const
+ {
+ ENSURE_OR_THROW( mpViewLayer->getCanvas(),
+ "ViewShape::getAntialiasingBorder(): Invalid ViewLayer canvas" );
+
+ const ::basegfx::B2DHomMatrix& rViewTransform(
+ mpViewLayer->getTransformation() );
+
+ // TODO(F1): As a quick shortcut (did not want to invert
+ // whole matrix here), taking only scale components of
+ // view transformation matrix. This will be wrong when
+ // e.g. shearing is involved.
+ const double nXBorder( ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE / rViewTransform.get(0,0) );
+ const double nYBorder( ::cppcanvas::Canvas::ANTIALIASING_EXTRA_SIZE / rViewTransform.get(1,1) );
+
+ return ::basegfx::B2DSize( nXBorder,
+ nYBorder );
+ }
+
+ bool ViewShape::enterAnimationMode()
+ {
+ mbForceUpdate = true;
+ mbAnimationMode = true;
+
+ return true;
+ }
+
+ void ViewShape::leaveAnimationMode()
+ {
+ mpSprite.reset();
+ mbAnimationMode = false;
+ mbForceUpdate = true;
+ }
+
+ bool ViewShape::update( const GDIMetaFileSharedPtr& rMtf,
+ const RenderArgs& rArgs,
+ int nUpdateFlags,
+ bool bIsVisible ) const
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::ViewShape::update()" );
+ ENSURE_OR_RETURN_FALSE( mpViewLayer->getCanvas(), "ViewShape::update(): Invalid layer canvas" );
+
+ // Shall we render to a sprite, or to a plain canvas?
+ if( isBackgroundDetached() )
+ return renderSprite( mpViewLayer,
+ rMtf,
+ rArgs.maOrigBounds,
+ rArgs.maBounds,
+ rArgs.maUnitBounds,
+ nUpdateFlags,
+ rArgs.mrAttr,
+ rArgs.mrSubsets,
+ rArgs.mnShapePriority,
+ bIsVisible );
+ else
+ return render( mpViewLayer->getCanvas(),
+ rMtf,
+ rArgs.maBounds,
+ rArgs.maUpdateBounds,
+ nUpdateFlags,
+ rArgs.mrAttr,
+ rArgs.mrSubsets,
+ bIsVisible );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/viewshape.hxx b/slideshow/source/engine/shapes/viewshape.hxx
new file mode 100644
index 000000000000..b92450d5335f
--- /dev/null
+++ b/slideshow/source/engine/shapes/viewshape.hxx
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWSHAPE_HXX
+#define INCLUDED_SLIDESHOW_VIEWSHAPE_HXX
+
+#include <cppcanvas/renderer.hxx>
+#include <cppcanvas/bitmap.hxx>
+
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include "tools.hxx"
+#include "shapeattributelayer.hxx"
+#include "animatedsprite.hxx"
+#include "viewlayer.hxx"
+#include "doctreenode.hxx"
+
+#include <vector>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class is the viewable representation of a draw
+ document's XShape, associated to a specific View
+
+ The class is able to render the associated XShape on
+ View implementations.
+ */
+ class ViewShape : private boost::noncopyable
+ {
+ public:
+ /** Create a ViewShape for the given View
+
+ @param rView
+ The associated View object.
+ */
+ explicit ViewShape( const ViewLayerSharedPtr& rViewLayer );
+
+ /** Query the associated view layer of this shape
+ */
+ ViewLayerSharedPtr getViewLayer() const;
+
+ /** Query dimension of a safety border around the shape for AA
+
+ If the view performs antialiasing, this method
+ calculates a safety border around the shape, in the
+ shape coordinate system, which is guaranteed to
+ include every pixel touched when rendering the shape.
+ */
+ ::basegfx::B2DSize getAntialiasingBorder() const;
+
+
+ // animation methods
+ //------------------------------------------------------------------
+
+ /** Notify the ViewShape that an animation starts now
+
+ This method enters animation mode on the associate
+ target view. The shape can be animated in parallel on
+ different views.
+
+ @return whether the mode change finished successfully.
+ */
+ bool enterAnimationMode();
+
+ /** Notify the ViewShape that it is no longer animated
+
+ This methods ends animation mode on the associate
+ target view
+ */
+ void leaveAnimationMode();
+
+ /** Query whether the ViewShape is currently animated
+
+ This method checks whether the ViewShape is currently in
+ animation mode.
+ */
+ bool isBackgroundDetached() const { return mbAnimationMode; }
+
+
+ // render methods
+ //------------------------------------------------------------------
+
+ enum UpdateFlags
+ {
+ NONE= 0,
+ TRANSFORMATION= 1,
+ CLIP= 2,
+ ALPHA= 4,
+ POSITION= 8,
+ CONTENT= 16,
+ FORCE= 32
+ };
+
+ struct RenderArgs
+ {
+ /** Create render argument struct
+
+ @param rOrigBounds
+ The initial shape bounds
+
+ @param rUpdateBounds
+ The area covered by the shape
+
+ @param rBounds
+ The current shape bounds
+
+ @param rAttr
+ The current shape attribute set. Can be NULL, for
+ default attributes. Attention: stored as a reference,
+ thus, parameter object must stay valid!
+
+ @param rSubsets
+ Vector of subset rendering ranges. Attention:
+ stored as a reference, thus, parameter object must
+ stay valid!
+
+ @param nPrio
+ Shape priority
+ */
+ RenderArgs( const ::basegfx::B2DRectangle& rOrigBounds,
+ const ::basegfx::B2DRectangle& rUpdateBounds,
+ const ::basegfx::B2DRectangle& rBounds,
+ const ::basegfx::B2DRectangle& rUnitBounds,
+ const ShapeAttributeLayerSharedPtr& rAttr,
+ const VectorOfDocTreeNodes& rSubsets,
+ double nPrio ) :
+ maOrigBounds( rOrigBounds ),
+ maUpdateBounds( rUpdateBounds ),
+ maBounds( rBounds ),
+ maUnitBounds( rUnitBounds ),
+ mrAttr( rAttr ),
+ mrSubsets( rSubsets ),
+ mnShapePriority( nPrio )
+ {
+ }
+
+ const ::basegfx::B2DRectangle maOrigBounds;
+ const ::basegfx::B2DRectangle maUpdateBounds;
+ const ::basegfx::B2DRectangle maBounds;
+ const ::basegfx::B2DRectangle maUnitBounds;
+ const ShapeAttributeLayerSharedPtr& mrAttr;
+ const VectorOfDocTreeNodes& mrSubsets;
+ const double mnShapePriority;
+ };
+
+ /** Update the ViewShape
+
+ This method updates the ViewShape on the associated
+ view. If the shape is currently animated, the render
+ target is the sprite, otherwise the view's
+ canvas. This method does not render anything, if the
+ update flags are 0.
+
+ @param rMtf
+ The metafile representation of the shape
+
+ @param rArgs
+ Parameter structure, containing all necessary arguments
+
+ @param nUpdateFlags
+ Bitmask of things to update. Use FORCE to force a repaint.
+
+ @param bIsVisible
+ When false, the shape is fully invisible (and possibly
+ don't need to be painted)
+
+ @return whether the rendering finished successfully.
+ */
+ bool update( const GDIMetaFileSharedPtr& rMtf,
+ const RenderArgs& rArgs,
+ int nUpdateFlags,
+ bool bIsVisible ) const;
+
+ /** Retrieve renderer for given canvas and metafile.
+
+ If necessary, the renderer is created or updated for
+ the metafile and attribute layer.
+
+ @return a renderer that renders to the given
+ destination canvas
+ */
+ ::cppcanvas::RendererSharedPtr getRenderer( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ShapeAttributeLayerSharedPtr& rAttr ) const;
+
+
+ private:
+ struct RendererCacheEntry
+ {
+ RendererCacheEntry() :
+ mpDestinationCanvas(),
+ mpRenderer(),
+ mpMtf(),
+ mpLastBitmap(),
+ mpLastBitmapCanvas()
+ {
+ }
+
+ ::cppcanvas::CanvasSharedPtr getDestinationCanvas()
+ {
+ return mpDestinationCanvas;
+ }
+
+ ::cppcanvas::CanvasSharedPtr mpDestinationCanvas;
+ ::cppcanvas::RendererSharedPtr mpRenderer;
+ GDIMetaFileSharedPtr mpMtf;
+ ::cppcanvas::BitmapSharedPtr mpLastBitmap;
+ ::cppcanvas::BitmapCanvasSharedPtr mpLastBitmapCanvas;
+ };
+
+ typedef ::std::vector< RendererCacheEntry > RendererCacheVector;
+
+
+ /** Prefetch Renderer for given canvas
+ */
+ bool prefetch( RendererCacheEntry& io_rCacheEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ShapeAttributeLayerSharedPtr& rAttr ) const;
+
+ /** Draw with prefetched Renderer to stored canvas
+
+ This method draws prefetched Renderer to its
+ associated canvas (which happens to be mpLastCanvas).
+ */
+ bool draw( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ShapeAttributeLayerSharedPtr& rAttr,
+ const ::basegfx::B2DHomMatrix& rTransform,
+ const ::basegfx::B2DPolyPolygon* pClip,
+ const VectorOfDocTreeNodes& rSubsets ) const;
+
+ /** Render shape to an active sprite
+ */
+ bool renderSprite( const ViewLayerSharedPtr& rViewLayer,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ::basegfx::B2DRectangle& rOrigBounds,
+ const ::basegfx::B2DRectangle& rBounds,
+ const ::basegfx::B2DRectangle& rUnitBounds,
+ int nUpdateFlags,
+ const ShapeAttributeLayerSharedPtr& pAttr,
+ const VectorOfDocTreeNodes& rSubsets,
+ double nPrio,
+ bool bIsVisible ) const;
+
+ /** Render shape to given canvas
+ */
+ bool render( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const GDIMetaFileSharedPtr& rMtf,
+ const ::basegfx::B2DRectangle& rBounds,
+ const ::basegfx::B2DRectangle& rUpdateBounds,
+ int nUpdateFlags,
+ const ShapeAttributeLayerSharedPtr& pAttr,
+ const VectorOfDocTreeNodes& rSubsets,
+ bool bIsVisible ) const;
+
+ /** Calc sprite size in pixel
+
+ Converts user coordinate system to device pixel, and
+ adds antialiasing border.
+
+ @param rUserSize
+ Size of the sprite in user coordinate system (doc coordinates)
+ */
+ ::basegfx::B2DSize calcSpriteSizePixel( const ::basegfx::B2DSize& rUserSize ) const;
+
+ enum{ MAX_RENDER_CACHE_ENTRIES=2 };
+
+ /** Retrieve a valid iterator to renderer cache entry
+
+ This method ensures that an internal limit of
+ MAX_RENDER_CACHE_ENTRIES is not exceeded.
+
+ @param rDestinationCanvas
+ Destination canvas to retrieve cache entry for
+
+ @return a valid iterator to a renderer cache entry for
+ the given canvas. The entry might be
+ default-constructed (if newly added)
+ */
+ RendererCacheVector::iterator getCacheEntry( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas ) const;
+
+ void invalidateRenderer() const;
+
+ /** The view layer this object is part of.
+
+ Needed for sprite creation
+ */
+ ViewLayerSharedPtr mpViewLayer;
+
+ /// A set of cached mtf/canvas combinations
+ mutable RendererCacheVector maRenderers;
+
+ /// The sprite object
+ mutable AnimatedSpriteSharedPtr mpSprite;
+
+ /// If true, render() calls go to the sprite
+ mutable bool mbAnimationMode;
+
+ /// If true, shape needs full repaint (and the sprite a setup, if any)
+ mutable bool mbForceUpdate;
+ };
+
+ typedef ::boost::shared_ptr< ViewShape > ViewShapeSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWSHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapesubset.cxx b/slideshow/source/engine/shapesubset.cxx
new file mode 100644
index 000000000000..2528c4a2279c
--- /dev/null
+++ b/slideshow/source/engine/shapesubset.cxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include "shapesubset.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ShapeSubset::ShapeSubset( const AttributableShapeSharedPtr& rOriginalShape,
+ const DocTreeNode& rTreeNode,
+ const SubsettableShapeManagerSharedPtr& rShapeManager ) :
+ mpOriginalShape( rOriginalShape ),
+ mpSubsetShape(),
+ maTreeNode( rTreeNode ),
+ mpShapeManager( rShapeManager )
+ {
+ ENSURE_OR_THROW( mpShapeManager,
+ "ShapeSubset::ShapeSubset(): Invalid shape manager" );
+ }
+
+ ShapeSubset::ShapeSubset( const ShapeSubsetSharedPtr& rOriginalSubset,
+ const DocTreeNode& rTreeNode ) :
+ mpOriginalShape( rOriginalSubset->mpSubsetShape ?
+ rOriginalSubset->mpSubsetShape :
+ rOriginalSubset->mpOriginalShape ),
+ mpSubsetShape(),
+ maTreeNode( rTreeNode ),
+ mpShapeManager( rOriginalSubset->mpShapeManager )
+ {
+ ENSURE_OR_THROW( mpShapeManager,
+ "ShapeSubset::ShapeSubset(): Invalid shape manager" );
+ ENSURE_OR_THROW( rOriginalSubset->maTreeNode.isEmpty() ||
+ (rTreeNode.getStartIndex() >= rOriginalSubset->maTreeNode.getStartIndex() &&
+ rTreeNode.getEndIndex() <= rOriginalSubset->maTreeNode.getEndIndex()),
+ "ShapeSubset::ShapeSubset(): Subset is bigger than parent" );
+ }
+
+ ShapeSubset::ShapeSubset( const AttributableShapeSharedPtr& rOriginalShape,
+ const SubsettableShapeManagerSharedPtr& rShapeManager ) :
+ mpOriginalShape( rOriginalShape ),
+ mpSubsetShape(),
+ maTreeNode(),
+ mpShapeManager( rShapeManager )
+ {
+ ENSURE_OR_THROW( mpShapeManager,
+ "ShapeSubset::ShapeSubset(): Invalid shape manager" );
+ }
+
+ ShapeSubset::~ShapeSubset()
+ {
+ try
+ {
+ // if not done yet: revoke subset from original
+ disableSubsetShape();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ AttributableShapeSharedPtr ShapeSubset::getSubsetShape() const
+ {
+ return mpSubsetShape ? mpSubsetShape : mpOriginalShape;
+ }
+
+ bool ShapeSubset::enableSubsetShape()
+ {
+ if( !mpSubsetShape &&
+ !maTreeNode.isEmpty() )
+ {
+ mpSubsetShape = mpShapeManager->getSubsetShape(
+ mpOriginalShape,
+ maTreeNode );
+ }
+
+ return mpSubsetShape;
+ }
+
+ void ShapeSubset::disableSubsetShape()
+ {
+ if( mpSubsetShape )
+ {
+ mpShapeManager->revokeSubset( mpOriginalShape,
+ mpSubsetShape );
+ mpSubsetShape.reset();
+ }
+ }
+
+ bool ShapeSubset::isFullSet() const
+ {
+ return maTreeNode.isEmpty();
+ }
+
+ DocTreeNode ShapeSubset::getSubset() const
+ {
+ return maTreeNode;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/layer.cxx b/slideshow/source/engine/slide/layer.cxx
new file mode 100644
index 000000000000..b2bca8752385
--- /dev/null
+++ b/slideshow/source/engine/slide/layer.cxx
@@ -0,0 +1,367 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b1drange.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+
+#include "layer.hxx"
+
+#include <boost/bind.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ Layer::Layer( const basegfx::B2DRange& rMaxLayerBounds,
+ Dummy ) :
+ maViewEntries(),
+ maBounds(),
+ maNewBounds(),
+ maMaxBounds( rMaxLayerBounds ),
+ mbBoundsDirty(false),
+ mbBackgroundLayer(true),
+ mbClipSet(false)
+ {
+ }
+
+ Layer::Layer( const basegfx::B2DRange& rMaxLayerBounds ) :
+ maViewEntries(),
+ maBounds(),
+ maNewBounds(),
+ maMaxBounds( rMaxLayerBounds ),
+ mbBoundsDirty(false),
+ mbBackgroundLayer(false),
+ mbClipSet(false)
+ {
+ }
+
+ ViewLayerSharedPtr Layer::addView( const ViewSharedPtr& rNewView )
+ {
+ OSL_ASSERT( rNewView );
+
+ ViewEntryVector::iterator aIter;
+ const ViewEntryVector::iterator aEnd( maViewEntries.end() );
+ if( (aIter=std::find_if( maViewEntries.begin(),
+ aEnd,
+ boost::bind<bool>(
+ std::equal_to< ViewSharedPtr >(),
+ boost::bind( &ViewEntry::getView, _1 ),
+ boost::cref( rNewView )))) != aEnd )
+ {
+ // already added - just return existing layer
+ return aIter->mpViewLayer;
+
+ }
+
+ // not yet added - create new view layer
+ ViewLayerSharedPtr pNewLayer;
+ if( mbBackgroundLayer )
+ pNewLayer = rNewView;
+ else
+ pNewLayer = rNewView->createViewLayer(maBounds);
+
+ // add to local list
+ maViewEntries.push_back(
+ ViewEntry( rNewView,
+ pNewLayer ));
+
+ return maViewEntries.back().mpViewLayer;
+ }
+
+ ViewLayerSharedPtr Layer::removeView( const ViewSharedPtr& rView )
+ {
+ OSL_ASSERT( rView );
+
+ ViewEntryVector::iterator aIter;
+ const ViewEntryVector::iterator aEnd( maViewEntries.end() );
+ if( (aIter=std::find_if( maViewEntries.begin(),
+ aEnd,
+ boost::bind<bool>(
+ std::equal_to< ViewSharedPtr >(),
+ boost::bind( &ViewEntry::getView, _1 ),
+ boost::cref( rView )))) == aEnd )
+ {
+ // View was not added/is already removed
+ return ViewLayerSharedPtr();
+ }
+
+ OSL_ENSURE( std::count_if( maViewEntries.begin(),
+ aEnd,
+ boost::bind<bool>(
+ std::equal_to< ViewSharedPtr >(),
+ boost::bind( &ViewEntry::getView, _1 ),
+ boost::cref( rView ))) == 1,
+ "Layer::removeView(): view added multiple times" );
+
+ ViewLayerSharedPtr pRet( aIter->mpViewLayer );
+ maViewEntries.erase(aIter);
+
+ return pRet;
+ }
+
+ void Layer::viewChanged( const ViewSharedPtr& rChangedView )
+ {
+ ViewEntryVector::iterator aIter;
+ const ViewEntryVector::iterator aEnd( maViewEntries.end() );
+ if( (aIter=std::find_if( maViewEntries.begin(),
+ aEnd,
+ boost::bind<bool>(
+ std::equal_to< ViewSharedPtr >(),
+ boost::bind( &ViewEntry::getView, _1 ),
+ boost::cref( rChangedView )))) !=
+ aEnd )
+ {
+ // adapt size of given ViewLayer - background layer
+ // resizes with view.
+ if( !mbBackgroundLayer )
+ aIter->mpViewLayer->resize(maBounds);
+ }
+ }
+
+ void Layer::viewsChanged()
+ {
+ // adapt size of given ViewLayer - background layer
+ // resizes with view.
+ if( !mbBackgroundLayer )
+ {
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind( &ViewLayer::resize,
+ boost::bind( &ViewEntry::getViewLayer,
+ _1 ),
+ boost::cref(maBounds)));
+ }
+ }
+
+ void Layer::setShapeViews( ShapeSharedPtr const& rShape ) const
+ {
+ rShape->clearAllViewLayers();
+
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind(&Shape::addViewLayer,
+ boost::cref(rShape),
+ boost::bind(&ViewEntry::getViewLayer,
+ _1),
+ false ));
+ }
+
+ void Layer::setPriority( const ::basegfx::B1DRange& rPrioRange )
+ {
+ if( !mbBackgroundLayer )
+ {
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind( &ViewLayer::setPriority,
+ boost::bind( &ViewEntry::getViewLayer,
+ _1 ),
+ boost::cref(rPrioRange)));
+ }
+ }
+
+ void Layer::addUpdateRange( ::basegfx::B2DRange const& rUpdateRange )
+ {
+ // TODO(Q1): move this to B2DMultiRange
+ if( !rUpdateRange.isEmpty() )
+ maUpdateAreas.appendElement( rUpdateRange,
+ basegfx::ORIENTATION_POSITIVE );
+ }
+
+ void Layer::updateBounds( ShapeSharedPtr const& rShape )
+ {
+ if( !mbBackgroundLayer )
+ {
+ if( !mbBoundsDirty )
+ maNewBounds.reset();
+
+ maNewBounds.expand( rShape->getUpdateArea() );
+ }
+
+ mbBoundsDirty = true;
+ }
+
+ bool Layer::commitBounds()
+ {
+ mbBoundsDirty = false;
+
+ if( mbBackgroundLayer )
+ return false;
+
+ if( maNewBounds == maBounds )
+ return false;
+
+ maBounds = maNewBounds;
+ if( std::count_if( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind( &ViewLayer::resize,
+ boost::bind( &ViewEntry::getViewLayer,
+ _1 ),
+ boost::cref(maBounds)) ) == 0 )
+ {
+ return false;
+ }
+
+ // layer content invalid, update areas have wrong
+ // coordinates/not sensible anymore.
+ clearUpdateRanges();
+
+ return true;
+ }
+
+ void Layer::clearUpdateRanges()
+ {
+ maUpdateAreas.clear();
+ }
+
+ void Layer::clearContent()
+ {
+ // clear content on all view layers
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind(
+ &ViewLayer::clear,
+ boost::bind(
+ &ViewEntry::getViewLayer,
+ _1)));
+
+ // layer content cleared, update areas are not sensible
+ // anymore.
+ clearUpdateRanges();
+ }
+
+ class LayerEndUpdate : private boost::noncopyable
+ {
+ public:
+ LayerEndUpdate( LayerSharedPtr const& rLayer ) :
+ mpLayer( rLayer )
+ {}
+
+ ~LayerEndUpdate() { if(mpLayer) mpLayer->endUpdate(); }
+
+ void dismiss() { mpLayer.reset(); }
+
+ private:
+ LayerSharedPtr mpLayer;
+ };
+
+ Layer::EndUpdater Layer::beginUpdate()
+ {
+ if( maUpdateAreas.count() )
+ {
+ // perform proper layer update. That means, setup proper
+ // clipping, and render each shape that intersects with
+ // the calculated update area
+ ::basegfx::B2DPolyPolygon aClip( maUpdateAreas.solveCrossovers() );
+ aClip = ::basegfx::tools::stripNeutralPolygons(aClip);
+ aClip = ::basegfx::tools::stripDispensablePolygons(aClip, false);
+
+ // actually, if there happen to be shapes with zero
+ // update area in the maUpdateAreas vector, the
+ // resulting clip polygon will be empty.
+ if( aClip.count() )
+ {
+ // set clip to all view layers
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind(
+ &ViewLayer::setClip,
+ boost::bind(
+ &ViewEntry::getViewLayer,
+ _1),
+ boost::cref(aClip)));
+
+ // clear update area on all view layers
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind(
+ &ViewLayer::clear,
+ boost::bind(
+ &ViewEntry::getViewLayer,
+ _1)));
+
+ mbClipSet = true;
+ }
+ }
+
+ return EndUpdater(new LayerEndUpdate(shared_from_this()));
+ }
+
+ void Layer::endUpdate()
+ {
+ if( mbClipSet )
+ {
+ mbClipSet = false;
+
+ basegfx::B2DPolyPolygon aEmptyClip;
+ std::for_each( maViewEntries.begin(),
+ maViewEntries.end(),
+ boost::bind(
+ &ViewLayer::setClip,
+ boost::bind(
+ &ViewEntry::getViewLayer,
+ _1),
+ boost::cref(aEmptyClip)));
+ }
+
+ clearUpdateRanges();
+ }
+
+ bool Layer::isInsideUpdateArea( ShapeSharedPtr const& rShape ) const
+ {
+ return maUpdateAreas.overlaps( rShape->getUpdateArea() );
+ }
+
+ LayerSharedPtr Layer::createBackgroundLayer( const basegfx::B2DRange& rMaxLayerBounds )
+ {
+ return LayerSharedPtr(new Layer( rMaxLayerBounds,
+ BackgroundLayer ));
+ }
+
+ LayerSharedPtr Layer::createLayer( const basegfx::B2DRange& rMaxLayerBounds )
+ {
+ return LayerSharedPtr( new Layer( rMaxLayerBounds ) );
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/layer.hxx b/slideshow/source/engine/slide/layer.hxx
new file mode 100644
index 000000000000..20ed39efabaf
--- /dev/null
+++ b/slideshow/source/engine/slide/layer.hxx
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_LAYER_HXX
+#define INCLUDED_SLIDESHOW_LAYER_HXX
+
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <cppcanvas/spritecanvas.hxx>
+
+#include "view.hxx"
+#include "animatableshape.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include <vector>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class LayerEndUpdate;
+
+ /* Definition of Layer class */
+
+ /** This class represents one layer of output on a Slide.
+
+ Layers group shapes for a certain depth region of a slide.
+
+ Since slides have a notion of depth, i.e. shapes on it
+ have a certain order in which they lie upon each other,
+ this layering must be modeled. A prime example for this
+ necessity are animations of shapes lying behind other
+ shapes. Then, everything behind the animated shape will be
+ in a background layer, the shape itself will be in an
+ animation layer, and everything before it will be in a
+ foreground layer (these layers are most preferrably
+ modeled as XSprite objects internally).
+
+ @attention All methods of this class are only supposed to
+ be called from the LayerManager. Normally, it shouldn't be
+ possible to get hold of an instance of this class at all.
+ */
+ class Layer : public boost::enable_shared_from_this<Layer>,
+ private boost::noncopyable
+ {
+ public:
+ typedef boost::shared_ptr<LayerEndUpdate> EndUpdater;
+
+ /** Create background layer
+
+ This method will create a layer without a ViewLayer,
+ i.e. one that displays directly on the background.
+
+ @param rMaxLayerBounds
+ Maximal bounds of this layer, in user
+ coordinates. This layer will never be larger or extend
+ outside these bounds.
+ */
+ static ::boost::shared_ptr< Layer > createBackgroundLayer( const basegfx::B2DRange& rMaxLayerBounds );
+
+ /** Create non-background layer
+
+ This method will create a layer in front of the
+ background, to contain shapes that should appear in
+ front of animated objects.
+
+ @param rMaxLayerBounds
+ Maximal bounds of this layer, in user
+ coordinates. This layer will never be larger or extend
+ outside these bounds.
+ */
+ static ::boost::shared_ptr< Layer > createLayer( const basegfx::B2DRange& rMaxLayerBounds );
+
+
+ /////////////////////////////////////////////////////////////////////
+
+
+ /** Predicate, whether this layer is the special
+ background layer
+
+ This method is mostly useful for checking invariants.
+ */
+ bool isBackgroundLayer() const { return mbBackgroundLayer; }
+
+ /** Add a view to this layer.
+
+ If the view is already added, this method does not add
+ it a second time, just returning the existing ViewLayer.
+
+ @param rNewView
+ New view to add to this layer.
+
+ @return the newly generated ViewLayer for this View
+ */
+ ViewLayerSharedPtr addView( const ViewSharedPtr& rNewView );
+
+ /** Remove a view
+
+ This method removes the view from this Layer and all
+ shapes included herein.
+
+ @return the ViewLayer of the removed Layer, if
+ any. Otherwise, NULL is returned.
+ */
+ ViewLayerSharedPtr removeView( const ViewSharedPtr& rView );
+
+ /** Notify that given ViewLayer has changed
+
+ @param rChangedView
+ This view's layer will get resized. Afterwards, a
+ complete repaint might be necessary.
+ */
+ void viewChanged( const ViewSharedPtr& rChangedView );
+
+ /** Notify that all ViewLayer have changed
+
+ This resizes all view layers. Afterwards, a complete
+ repaint might be necessary.
+ */
+ void viewsChanged();
+
+ /** Init shape with this layer's views
+
+ @param rShape
+ The shape, that will subsequently display on this
+ layer's views
+ */
+ void setShapeViews( ShapeSharedPtr const& rShape ) const;
+
+
+ /////////////////////////////////////////////////////////////////////
+
+
+ /** Change layer priority range.
+
+ The layer priority affects the position of the layer
+ in the z direction (i.e. before/behind which other
+ layers this one appears). The higher the prio, the
+ further on top of the layer stack this one appears.
+
+ @param rPrioRange
+ The priority range of differing layers must not
+ intersect
+ */
+ void setPriority( const ::basegfx::B1DRange& rPrioRange );
+
+ /** Add an area that needs update
+
+ @param rUpdateRange
+ Area on this layer that needs update
+ */
+ void addUpdateRange( ::basegfx::B2DRange const& rUpdateRange );
+
+ /** Whether any update ranges have been added
+
+ @return true, if any non-empty addUpdateRange() calls
+ have been made since the last render()/update() call.
+ */
+ bool isUpdatePending() const { return maUpdateAreas.count()!=0; }
+
+ /** Update layer bound rect from shape bounds
+ */
+ void updateBounds( ShapeSharedPtr const& rShape );
+
+ /** Commit collected layer bounds to ViewLayer
+
+ Call this method when you're done adding new shapes to
+ the layer.
+
+ @return true, if layer needed a resize (which
+ invalidates its content - you have to repaint all
+ contained shapes!)
+ */
+ bool commitBounds();
+
+ /** Clear all registered update ranges
+
+ This method clears all update ranges that are
+ registered at this layer.
+ */
+ void clearUpdateRanges();
+
+ /** Clear whole layer content
+
+ This method clears the whole layer content. As a
+ byproduct, all update ranges are cleared as well. It
+ makes no sense to maintain them any further, since
+ they only serve for partial updates.
+ */
+ void clearContent();
+
+ /** Init layer update.
+
+ This method initializes a full layer update of the
+ update area. When the last copy of the returned
+ EndUpdater is destroyed, the Layer leaves update mode
+ again.
+
+ @return a update end RAII object.
+ */
+ EndUpdater beginUpdate();
+
+ /** Finish layer update
+
+ Resets clipping and transformation to normal values
+ */
+ void endUpdate();
+
+ /** Check whether given shape is inside current update area.
+
+ @return true, if the given shape is at least partially
+ inside the current update area.
+ */
+ bool isInsideUpdateArea( ShapeSharedPtr const& rShape ) const;
+
+ private:
+ enum Dummy{ BackgroundLayer };
+
+ /** Create background layer
+
+ This constructor will create a layer without a
+ ViewLayer, i.e. one that displays directly on the
+ background.
+
+ @param rMaxLayerBounds
+ Maximal bounds of this layer, in user
+ coordinates. This layer will never be larger or extend
+ outside these bounds.
+
+ @param eFlag
+ Dummy parameter, to disambiguate from normal layer
+ constructor
+ */
+ Layer( const basegfx::B2DRange& rMaxLayerBounds,
+ Dummy eFlag );
+
+ /** Create non-background layer
+
+ This constructor will create a layer in front of the
+ background, to contain shapes that should appear in
+ front of animated objects.
+
+ @param rMaxLayerBounds
+ Maximal bounds of this layer, in user
+ coordinates. This layer will never be larger or extend
+ outside these bounds.
+ */
+ explicit Layer( const basegfx::B2DRange& rMaxLayerBounds );
+
+ struct ViewEntry
+ {
+ ViewEntry( const ViewSharedPtr& rView,
+ const ViewLayerSharedPtr& rViewLayer ) :
+ mpView( rView ),
+ mpViewLayer( rViewLayer )
+ {}
+
+ ViewSharedPtr mpView;
+ ViewLayerSharedPtr mpViewLayer;
+
+ // for generic algo access (which needs actual functions)
+ const ViewSharedPtr& getView() const { return mpView; }
+ const ViewLayerSharedPtr& getViewLayer() const { return mpViewLayer; }
+ };
+
+ typedef ::std::vector< ViewEntry > ViewEntryVector;
+
+ ViewEntryVector maViewEntries;
+ basegfx::B2DPolyRange maUpdateAreas;
+ basegfx::B2DRange maBounds;
+ basegfx::B2DRange maNewBounds;
+ const basegfx::B2DRange maMaxBounds; // maBounds is clipped against this
+ bool mbBoundsDirty; // true, if view layers need resize
+ bool mbBackgroundLayer; // true, if this
+ // layer is the
+ // special
+ // background layer
+ bool mbClipSet; // true, if beginUpdate set a clip
+ };
+
+ typedef ::boost::shared_ptr< Layer > LayerSharedPtr;
+ typedef ::boost::weak_ptr< Layer > LayerWeakPtr;
+ typedef ::std::vector< LayerSharedPtr > LayerVector;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_LAYER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/layermanager.cxx b/slideshow/source/engine/slide/layermanager.cxx
new file mode 100644
index 000000000000..0bd52febbb82
--- /dev/null
+++ b/slideshow/source/engine/slide/layermanager.cxx
@@ -0,0 +1,926 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <basegfx/range/b1drange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+#include "layermanager.hxx"
+
+using namespace ::com::sun::star;
+
+namespace boost
+{
+ // add operator!= for weak_ptr
+ inline bool operator!=( slideshow::internal::LayerWeakPtr const& rLHS,
+ slideshow::internal::LayerWeakPtr const& rRHS )
+ {
+ return (rLHS<rRHS) || (rRHS<rLHS);
+ }
+}
+
+namespace slideshow
+{
+ namespace internal
+ {
+ template<typename LayerFunc,
+ typename ShapeFunc> void LayerManager::manageViews(
+ LayerFunc layerFunc,
+ ShapeFunc shapeFunc )
+ {
+ LayerSharedPtr pCurrLayer;
+ ViewLayerSharedPtr pCurrViewLayer;
+ LayerShapeMap::const_iterator aIter( maAllShapes.begin() );
+ const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() );
+ while( aIter != aEnd )
+ {
+ LayerSharedPtr pLayer = aIter->second.lock();
+ if( pLayer && pLayer != pCurrLayer )
+ {
+ pCurrLayer = pLayer;
+ pCurrViewLayer = layerFunc(pCurrLayer);
+ }
+
+ if( pCurrViewLayer )
+ shapeFunc(aIter->first,pCurrViewLayer);
+
+ ++aIter;
+ }
+ }
+
+ LayerManager::LayerManager( const UnoViewContainer& rViews,
+ const ::basegfx::B2DRange& rPageBounds,
+ bool bDisableAnimationZOrder ) :
+ mrViews(rViews),
+ maLayers(),
+ maXShapeHash( 101 ),
+ maAllShapes(),
+ maUpdateShapes(),
+ maPageBounds( rPageBounds ),
+ mnActiveSprites(0),
+ mbLayerAssociationDirty(false),
+ mbActive(false),
+ mbDisableAnimationZOrder(bDisableAnimationZOrder)
+ {
+ // prevent frequent resizes (won't have more than 4 layers
+ // for 99.9% of the cases)
+ maLayers.reserve(4);
+
+ // create initial background layer
+ maLayers.push_back(
+ Layer::createBackgroundLayer(
+ maPageBounds ));
+
+ // init views
+ std::for_each( mrViews.begin(),
+ mrViews.end(),
+ ::boost::bind(&LayerManager::viewAdded,
+ this,
+ _1) );
+ }
+
+ void LayerManager::activate( bool bSlideBackgoundPainted )
+ {
+ mbActive = true;
+ maUpdateShapes.clear(); // update gets forced via area, or
+ // has happend outside already
+
+ if( !bSlideBackgoundPainted )
+ {
+ std::for_each(mrViews.begin(),
+ mrViews.end(),
+ boost::mem_fn(&View::clearAll));
+
+ // force update of whole slide area
+ std::for_each( maLayers.begin(),
+ maLayers.end(),
+ boost::bind( &Layer::addUpdateRange,
+ _1,
+ boost::cref(maPageBounds) ));
+ }
+ else
+ {
+ // clear all possibly pending update areas - content
+ // is there, already
+ std::for_each( maLayers.begin(),
+ maLayers.end(),
+ boost::mem_fn( &Layer::clearUpdateRanges ));
+ }
+
+ updateShapeLayers( bSlideBackgoundPainted );
+ }
+
+ void LayerManager::deactivate()
+ {
+ // TODO(F3): This is mostly a hack. Problem is, there's
+ // currently no smart way of telling shapes "remove your
+ // sprites". Others, like MediaShapes, listen to
+ // start/stop animation events, which is too much overhead
+ // for all shapes, though.
+
+ const bool bMoreThanOneLayer(maLayers.size() > 1);
+ if( mnActiveSprites || bMoreThanOneLayer )
+ {
+ // clear all viewlayers, dump everything but the
+ // background layer - this will also remove all shape
+ // sprites
+ std::for_each(maAllShapes.begin(),
+ maAllShapes.end(),
+ boost::bind( &Shape::clearAllViewLayers,
+ boost::bind( std::select1st<LayerShapeMap::value_type>(),
+ _1 )));
+
+ for (LayerShapeMap::iterator
+ iShape (maAllShapes.begin()),
+ iEnd (maAllShapes.end());
+ iShape!=iEnd;
+ ++iShape)
+ {
+ iShape->second.reset();
+ }
+
+ if( bMoreThanOneLayer )
+ maLayers.erase(maLayers.begin()+1,
+ maLayers.end());
+
+ mbLayerAssociationDirty = true;
+ }
+
+ mbActive = false;
+
+ // only background layer left
+ OSL_ASSERT( maLayers.size() == 1 && maLayers.front()->isBackgroundLayer() );
+ }
+
+ void LayerManager::viewAdded( const UnoViewSharedPtr& rView )
+ {
+ // view must be member of mrViews container
+ OSL_ASSERT( std::find(mrViews.begin(),
+ mrViews.end(),
+ rView) != mrViews.end() );
+
+ // init view content
+ if( mbActive )
+ rView->clearAll();
+
+ // add View to all registered shapes
+ manageViews(
+ boost::bind(&Layer::addView,
+ _1,
+ boost::cref(rView)),
+ // repaint on view add
+ boost::bind(&Shape::addViewLayer,
+ _1,
+ _2,
+ true) );
+
+ // in case we haven't reached all layers from the
+ // maAllShapes, issue addView again for good measure
+ std::for_each( maLayers.begin(),
+ maLayers.end(),
+ boost::bind( &Layer::addView,
+ _1,
+ boost::cref(rView) ));
+ }
+
+ void LayerManager::viewRemoved( const UnoViewSharedPtr& rView )
+ {
+ // view must not be member of mrViews container anymore
+ OSL_ASSERT( std::find(mrViews.begin(),
+ mrViews.end(),
+ rView) == mrViews.end() );
+
+ // remove View from all registered shapes
+ manageViews(
+ boost::bind(&Layer::removeView,
+ _1,
+ boost::cref(rView)),
+ boost::bind(&Shape::removeViewLayer,
+ _1,
+ _2) );
+
+ // in case we haven't reached all layers from the
+ // maAllShapes, issue removeView again for good measure
+ std::for_each( maLayers.begin(),
+ maLayers.end(),
+ boost::bind( &Layer::removeView,
+ _1,
+ boost::cref(rView) ));
+ }
+
+ void LayerManager::viewChanged( const UnoViewSharedPtr& rView )
+ {
+ (void)rView;
+
+ // view must be member of mrViews container
+ OSL_ASSERT( std::find(mrViews.begin(),
+ mrViews.end(),
+ rView) != mrViews.end() );
+
+ // TODO(P2): selectively update only changed view
+ viewsChanged();
+ }
+
+ void LayerManager::viewsChanged()
+ {
+ if( !mbActive )
+ return;
+
+ // clear view area
+ ::std::for_each( mrViews.begin(),
+ mrViews.end(),
+ ::boost::mem_fn(&View::clearAll) );
+
+ // TODO(F3): resize and repaint all layers
+
+ // render all shapes
+ std::for_each( maAllShapes.begin(),
+ maAllShapes.end(),
+ boost::bind(&Shape::render,
+ boost::bind( ::std::select1st<LayerShapeMap::value_type>(), _1)) );
+ }
+
+ void LayerManager::addShape( const ShapeSharedPtr& rShape )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+ ENSURE_OR_THROW( rShape, "LayerManager::addShape(): invalid Shape" );
+
+ // add shape to XShape hash map
+ if( !maXShapeHash.insert(
+ XShapeHash::value_type( rShape->getXShape(),
+ rShape) ).second )
+ {
+ // entry already present, nothing to do
+ return;
+ }
+
+ // add shape to appropriate layer
+ implAddShape( rShape );
+ }
+
+ void LayerManager::putShape2BackgroundLayer( LayerShapeMap::value_type& rShapeEntry )
+ {
+ LayerSharedPtr& rBgLayer( maLayers.front() );
+ rBgLayer->setShapeViews(rShapeEntry.first);
+ rShapeEntry.second = rBgLayer;
+ }
+
+ void LayerManager::implAddShape( const ShapeSharedPtr& rShape )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+ ENSURE_OR_THROW( rShape, "LayerManager::implAddShape(): invalid Shape" );
+
+ LayerShapeMap::value_type aValue (rShape, LayerWeakPtr());
+
+ OSL_ASSERT( maAllShapes.find(rShape) == maAllShapes.end() ); // shape must not be added already
+ mbLayerAssociationDirty = true;
+
+ if( mbDisableAnimationZOrder )
+ putShape2BackgroundLayer(
+ *maAllShapes.insert(aValue).first );
+ else
+ maAllShapes.insert(aValue);
+
+ // update shape, it's just added and not yet painted
+ if( rShape->isVisible() )
+ notifyShapeUpdate( rShape );
+ }
+
+ bool LayerManager::removeShape( const ShapeSharedPtr& rShape )
+ {
+ // remove shape from XShape hash map
+ if( maXShapeHash.erase( rShape->getXShape() ) == 0 )
+ return false; // shape not in map
+
+ OSL_ASSERT( maAllShapes.find(rShape) != maAllShapes.end() );
+
+ implRemoveShape( rShape );
+
+ return true;
+ }
+
+ void LayerManager::implRemoveShape( const ShapeSharedPtr& rShape )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+ ENSURE_OR_THROW( rShape, "LayerManager::implRemoveShape(): invalid Shape" );
+
+ const LayerShapeMap::iterator aShapeEntry( maAllShapes.find(rShape) );
+
+ if( aShapeEntry == maAllShapes.end() )
+ return;
+
+ const bool bShapeUpdateNotified = maUpdateShapes.erase( rShape ) != 0;
+
+ // Enter shape area to the update area, but only if shape
+ // is visible and not in sprite mode (otherwise, updating
+ // the area doesn't do actual harm, but costs time)
+ // Actually, also add it if it was listed in
+ // maUpdateShapes (might have just gone invisible).
+ if( bShapeUpdateNotified ||
+ (rShape->isVisible() &&
+ !rShape->isBackgroundDetached()) )
+ {
+ LayerSharedPtr pLayer = aShapeEntry->second.lock();
+ if( pLayer )
+ {
+ // store area early, once the shape is removed from
+ // the layers, it no longer has any view references
+ pLayer->addUpdateRange( rShape->getUpdateArea() );
+ }
+ }
+
+ rShape->clearAllViewLayers();
+ maAllShapes.erase( aShapeEntry );
+
+ mbLayerAssociationDirty = true;
+ }
+
+ ShapeSharedPtr LayerManager::lookupShape( const uno::Reference< drawing::XShape >& xShape ) const
+ {
+ ENSURE_OR_THROW( xShape.is(), "LayerManager::lookupShape(): invalid Shape" );
+
+ const XShapeHash::const_iterator aIter( maXShapeHash.find( xShape ));
+ if( aIter == maXShapeHash.end() )
+ return ShapeSharedPtr(); // not found
+
+ // found, return data part of entry pair.
+ return aIter->second;
+ }
+
+ AttributableShapeSharedPtr LayerManager::getSubsetShape( const AttributableShapeSharedPtr& rOrigShape,
+ const DocTreeNode& rTreeNode )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+
+ AttributableShapeSharedPtr pSubset;
+
+ // shape already added?
+ if( rOrigShape->createSubset( pSubset,
+ rTreeNode ) )
+ {
+ OSL_ENSURE( pSubset, "LayerManager::getSubsetShape(): failed to create subset" );
+
+ // don't add to shape hash, we're dupes to the
+ // original XShape anyway - all subset shapes return
+ // the same XShape as the original one.
+
+ // add shape to corresponding layer
+ implAddShape( pSubset );
+
+ // update original shape, it now shows less content
+ // (the subset is removed from its displayed
+ // output). Subset shape is updated within
+ // implAddShape().
+ if( rOrigShape->isVisible() )
+ notifyShapeUpdate( rOrigShape );
+ }
+
+ return pSubset;
+ }
+
+ void LayerManager::revokeSubset( const AttributableShapeSharedPtr& rOrigShape,
+ const AttributableShapeSharedPtr& rSubsetShape )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+
+ if( rOrigShape->revokeSubset( rSubsetShape ) )
+ {
+ OSL_ASSERT( maAllShapes.find(rSubsetShape) != maAllShapes.end() );
+
+ implRemoveShape( rSubsetShape );
+
+ // update original shape, it now shows more content
+ // (the subset is added back to its displayed output)
+ if( rOrigShape->isVisible() )
+ notifyShapeUpdate( rOrigShape );
+ }
+ }
+
+ void LayerManager::enterAnimationMode( const AnimatableShapeSharedPtr& rShape )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+ ENSURE_OR_THROW( rShape, "LayerManager::enterAnimationMode(): invalid Shape" );
+
+ const bool bPrevAnimState( rShape->isBackgroundDetached() );
+
+ rShape->enterAnimationMode();
+
+ // if this call _really_ enabled the animation mode at
+ // rShape, insert it to our enter animation queue, to
+ // perform the necessary layer reorg lazily on
+ // LayerManager::update()/render().
+ if( bPrevAnimState != rShape->isBackgroundDetached() )
+ {
+ ++mnActiveSprites;
+ mbLayerAssociationDirty = true;
+
+ // area needs update (shape is removed from normal
+ // slide, and now rendered as an autonomous
+ // sprite). store in update set
+ if( rShape->isVisible() )
+ addUpdateArea( rShape );
+ }
+
+ // TODO(P1): this can lead to potential wasted effort, if
+ // a shape gets toggled animated/unanimated a few times
+ // between two frames, returning to the original state.
+ }
+
+ void LayerManager::leaveAnimationMode( const AnimatableShapeSharedPtr& rShape )
+ {
+ ENSURE_OR_THROW( !maLayers.empty(), "LayerManager::leaveAnimationMode(): no layers" );
+ ENSURE_OR_THROW( rShape, "LayerManager::leaveAnimationMode(): invalid Shape" );
+
+ const bool bPrevAnimState( rShape->isBackgroundDetached() );
+
+ rShape->leaveAnimationMode();
+
+ // if this call _really_ ended the animation mode at
+ // rShape, insert it to our leave animation queue, to
+ // perform the necessary layer reorg lazily on
+ // LayerManager::update()/render().
+ if( bPrevAnimState != rShape->isBackgroundDetached() )
+ {
+ --mnActiveSprites;
+ mbLayerAssociationDirty = true;
+
+ // shape needs update, no previous rendering, fast
+ // update possible.
+ if( rShape->isVisible() )
+ notifyShapeUpdate( rShape );
+ }
+
+ // TODO(P1): this can lead to potential wasted effort, if
+ // a shape gets toggled animated/unanimated a few times
+ // between two frames, returning to the original state.
+ }
+
+ void LayerManager::notifyShapeUpdate( const ShapeSharedPtr& rShape )
+ {
+ if( !mbActive || mrViews.empty() )
+ return;
+
+ // hidden sprite-shape needs render() call still, to hide sprite
+ if( rShape->isVisible() || rShape->isBackgroundDetached() )
+ maUpdateShapes.insert( rShape );
+ else
+ addUpdateArea( rShape );
+ }
+
+ bool LayerManager::isUpdatePending() const
+ {
+ if( !mbActive )
+ return false;
+
+ if( mbLayerAssociationDirty || !maUpdateShapes.empty() )
+ return true;
+
+ const LayerVector::const_iterator aEnd( maLayers.end() );
+ if( std::find_if( maLayers.begin(),
+ aEnd,
+ boost::mem_fn(&Layer::isUpdatePending)) != aEnd )
+ return true;
+
+ return false;
+ }
+
+ bool LayerManager::updateSprites()
+ {
+ bool bRet(true);
+
+ // send update() calls to every shape in the
+ // maUpdateShapes set, which is _animated_ (i.e. a
+ // sprite).
+ const ShapeUpdateSet::const_iterator aEnd=maUpdateShapes.end();
+ ShapeUpdateSet::const_iterator aCurrShape=maUpdateShapes.begin();
+ while( aCurrShape != aEnd )
+ {
+ if( (*aCurrShape)->isBackgroundDetached() )
+ {
+ // can update shape directly, without
+ // affecting layer content (shape is
+ // currently displayed in a sprite)
+ if( !(*aCurrShape)->update() )
+ bRet = false; // delay error exit
+ }
+ else
+ {
+ // TODO(P2): addUpdateArea() involves log(n)
+ // search for shape layer. Have a frequent
+ // shape/layer association cache, or ptr back to
+ // layer at the shape?
+
+ // cannot update shape directly, it's not
+ // animated and update() calls will prolly
+ // overwrite other page content.
+ addUpdateArea( *aCurrShape );
+ }
+
+ ++aCurrShape;
+ }
+
+ maUpdateShapes.clear();
+
+ return bRet;
+ }
+
+ bool LayerManager::update()
+ {
+ bool bRet = true;
+
+ if( !mbActive )
+ return bRet;
+
+ // going to render - better flush any pending layer reorg
+ // now
+ updateShapeLayers(false);
+
+ // all sprites
+ bRet = updateSprites();
+
+ // any non-sprite update areas left?
+ if( std::find_if( maLayers.begin(),
+ maLayers.end(),
+ boost::mem_fn( &Layer::isUpdatePending )) == maLayers.end() )
+ return bRet; // nope, done.
+
+ // update each shape on each layer, that has
+ // isUpdatePending()
+ bool bIsCurrLayerUpdating(false);
+ Layer::EndUpdater aEndUpdater;
+ LayerSharedPtr pCurrLayer;
+ LayerShapeMap::const_iterator aIter( maAllShapes.begin() );
+ const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() );
+ while( aIter != aEnd )
+ {
+ LayerSharedPtr pLayer = aIter->second.lock();
+ if( pLayer != pCurrLayer )
+ {
+ pCurrLayer = pLayer;
+ bIsCurrLayerUpdating = pCurrLayer->isUpdatePending();
+
+ if( bIsCurrLayerUpdating )
+ aEndUpdater = pCurrLayer->beginUpdate();
+ }
+
+ if( bIsCurrLayerUpdating &&
+ !aIter->first->isBackgroundDetached() &&
+ pCurrLayer->isInsideUpdateArea(aIter->first) )
+ {
+ if( !aIter->first->render() )
+ bRet = false;
+ }
+
+ ++aIter;
+ }
+
+ return bRet;
+ }
+
+ namespace
+ {
+ /** Little wrapper around a Canvas, to render one-shot
+ into a canvas
+ */
+ class DummyLayer : public ViewLayer
+ {
+ public:
+ explicit DummyLayer( const ::cppcanvas::CanvasSharedPtr& rCanvas ) :
+ mpCanvas( rCanvas )
+ {
+ }
+
+ virtual bool isOnView(boost::shared_ptr<View> const& /*rView*/) const
+ {
+ return true; // visible on all views
+ }
+
+ virtual ::cppcanvas::CanvasSharedPtr getCanvas() const
+ {
+ return mpCanvas;
+ }
+
+ virtual void clear() const
+ {
+ // NOOP
+ }
+
+ virtual void clearAll() const
+ {
+ // NOOP
+ }
+
+ virtual ::cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& /*rSpriteSizePixel*/,
+ double /*nSpritePrio*/ ) const
+ {
+ ENSURE_OR_THROW( false,
+ "DummyLayer::createSprite(): This method is not supposed to be called!" );
+ return ::cppcanvas::CustomSpriteSharedPtr();
+ }
+
+ virtual void setPriority( const basegfx::B1DRange& /*rRange*/ )
+ {
+ OSL_ENSURE( false,
+ "BitmapView::setPriority(): This method is not supposed to be called!" );
+ }
+
+ virtual ::basegfx::B2DHomMatrix getTransformation() const
+ {
+ return mpCanvas->getTransformation();
+ }
+
+ virtual ::basegfx::B2DHomMatrix getSpriteTransformation() const
+ {
+ OSL_ENSURE( false,
+ "BitmapView::getSpriteTransformation(): This method is not supposed to be called!" );
+ return ::basegfx::B2DHomMatrix();
+ }
+
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& /*rClip*/ )
+ {
+ OSL_ENSURE( false,
+ "BitmapView::setClip(): This method is not supposed to be called!" );
+ }
+
+ virtual bool resize( const ::basegfx::B2DRange& /*rArea*/ )
+ {
+ OSL_ENSURE( false,
+ "BitmapView::resize(): This method is not supposed to be called!" );
+ return false;
+ }
+
+ private:
+ ::cppcanvas::CanvasSharedPtr mpCanvas;
+ };
+ }
+
+ bool LayerManager::renderTo( const ::cppcanvas::CanvasSharedPtr& rTargetCanvas ) const
+ {
+ bool bRet( true );
+ ViewLayerSharedPtr pTmpLayer( new DummyLayer( rTargetCanvas ) );
+
+ LayerShapeMap::const_iterator aIter( maAllShapes.begin() );
+ const LayerShapeMap::const_iterator aEnd ( maAllShapes.end() );
+ while( aIter != aEnd )
+ {
+ try
+ {
+ // forward to all shape's addViewLayer method (which
+ // we request to render the Shape on the new
+ // ViewLayer. Since we add the shapes in the
+ // maShapeSet order (which is also the render order),
+ // this is equivalent to a subsequent render() call)
+ aIter->first->addViewLayer( pTmpLayer,
+ true );
+
+ // and remove again, this is only temporary
+ aIter->first->removeViewLayer( pTmpLayer );
+ }
+ catch( uno::Exception& )
+ {
+ // TODO(E1): Might be superfluous. Nowadays,
+ // addViewLayer swallows all errors, anyway.
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ // at least one shape could not be rendered
+ bRet = false;
+ }
+
+ ++aIter;
+ }
+
+ return bRet;
+ }
+
+ void LayerManager::addUpdateArea( ShapeSharedPtr const& rShape )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+ ENSURE_OR_THROW( rShape, "LayerManager::addUpdateArea(): invalid Shape" );
+
+ const LayerShapeMap::const_iterator aShapeEntry( maAllShapes.find(rShape) );
+
+ if( aShapeEntry == maAllShapes.end() )
+ return;
+
+ LayerSharedPtr pLayer = aShapeEntry->second.lock();
+ if( pLayer )
+ pLayer->addUpdateRange( rShape->getUpdateArea() );
+ }
+
+ void LayerManager::commitLayerChanges( std::size_t nCurrLayerIndex,
+ LayerShapeMap::const_iterator aFirstLayerShape,
+ LayerShapeMap::const_iterator aEndLayerShapes )
+ {
+ const bool bLayerExists( maLayers.size() > nCurrLayerIndex );
+ if( bLayerExists )
+ {
+ const LayerSharedPtr& rLayer( maLayers.at(nCurrLayerIndex) );
+ const bool bLayerResized( rLayer->commitBounds() );
+ rLayer->setPriority( basegfx::B1DRange(nCurrLayerIndex,
+ nCurrLayerIndex+1) );
+
+ if( bLayerResized )
+ {
+ // need to re-render whole layer - start from
+ // clean state
+ rLayer->clearContent();
+
+ // render and remove from update set
+ while( aFirstLayerShape != aEndLayerShapes )
+ {
+ maUpdateShapes.erase(aFirstLayerShape->first);
+ aFirstLayerShape->first->render();
+ ++aFirstLayerShape;
+ }
+ }
+ }
+ }
+
+ LayerSharedPtr LayerManager::createForegroundLayer() const
+ {
+ OSL_ASSERT( mbActive );
+
+ LayerSharedPtr pLayer( Layer::createLayer(
+ maPageBounds ));
+
+ // create ViewLayers for all registered views, and add to
+ // newly created layer.
+ ::std::for_each( mrViews.begin(),
+ mrViews.end(),
+ boost::bind( &Layer::addView,
+ boost::cref(pLayer),
+ _1 ));
+
+ return pLayer;
+ }
+
+ void LayerManager::updateShapeLayers( bool bBackgroundLayerPainted )
+ {
+ OSL_ASSERT( !maLayers.empty() ); // always at least background layer
+ OSL_ASSERT( mbActive );
+
+ // do we need to process shapes?
+ if( !mbLayerAssociationDirty )
+ return;
+
+ if( mbDisableAnimationZOrder )
+ {
+ // layer setup happened elsewhere, is only bg layer
+ // anyway.
+ mbLayerAssociationDirty = false;
+ return;
+ }
+
+ // scan through maAllShapes, and determine shape animation
+ // discontinuities: when a shape that has
+ // isBackgroundDetached() return false follows a shape
+ // with isBackgroundDetached() true, the former and all
+ // following ones must be moved into an own layer.
+
+ // to avoid tons of temporaries, create weak_ptr to Layers
+ // beforehand
+ std::vector< LayerWeakPtr > aWeakLayers(maLayers.size());
+ std::copy(maLayers.begin(),maLayers.end(),aWeakLayers.begin());
+
+ std::size_t nCurrLayerIndex(0);
+ bool bIsBackgroundLayer(true);
+ bool bLastWasBackgroundDetached(false); // last shape sprite state
+ LayerShapeMap::iterator aCurrShapeEntry( maAllShapes.begin() );
+ LayerShapeMap::iterator aCurrLayerFirstShapeEntry( maAllShapes.begin() );
+ const LayerShapeMap::iterator aEndShapeEntry ( maAllShapes.end() );
+ ShapeUpdateSet aUpdatedShapes; // shapes that need update
+ while( aCurrShapeEntry != aEndShapeEntry )
+ {
+ const ShapeSharedPtr pCurrShape( aCurrShapeEntry->first );
+ const bool bThisIsBackgroundDetached(
+ pCurrShape->isBackgroundDetached() );
+
+ if( bLastWasBackgroundDetached == true &&
+ bThisIsBackgroundDetached == false )
+ {
+ // discontinuity found - current shape needs to
+ // get into a new layer
+ // --------------------------------------------
+
+ // commit changes to previous layer
+ commitLayerChanges(nCurrLayerIndex,
+ aCurrLayerFirstShapeEntry,
+ aCurrShapeEntry);
+ aCurrLayerFirstShapeEntry=aCurrShapeEntry;
+ ++nCurrLayerIndex;
+ bIsBackgroundLayer = false;
+
+ if( aWeakLayers.size() <= nCurrLayerIndex ||
+ aWeakLayers.at(nCurrLayerIndex) != aCurrShapeEntry->second )
+ {
+ // no more layers left, or shape was not
+ // member of this layer - create a new one
+ maLayers.insert( maLayers.begin()+nCurrLayerIndex,
+ createForegroundLayer() );
+ aWeakLayers.insert( aWeakLayers.begin()+nCurrLayerIndex,
+ maLayers[nCurrLayerIndex] );
+ }
+ }
+
+ OSL_ASSERT( maLayers.size() == aWeakLayers.size() );
+
+ // note: using indices here, since vector::insert
+ // above invalidates iterators
+ LayerSharedPtr& rCurrLayer( maLayers.at(nCurrLayerIndex) );
+ LayerWeakPtr& rCurrWeakLayer( aWeakLayers.at(nCurrLayerIndex) );
+ if( rCurrWeakLayer != aCurrShapeEntry->second )
+ {
+ // mismatch: shape is not contained in current
+ // layer - move shape to that layer, then.
+ maLayers.at(nCurrLayerIndex)->setShapeViews(
+ pCurrShape );
+
+ // layer got new shape(s), need full repaint, if
+ // non-sprite shape
+ if( !bThisIsBackgroundDetached && pCurrShape->isVisible() )
+ {
+ LayerSharedPtr pOldLayer( aCurrShapeEntry->second.lock() );
+ if( pOldLayer )
+ {
+ // old layer still valid? then we need to
+ // repaint former shape area
+ pOldLayer->addUpdateRange(
+ pCurrShape->getUpdateArea() );
+ }
+
+ // render on new layer (only if not
+ // explicitely disabled)
+ if( !(bBackgroundLayerPainted && bIsBackgroundLayer) )
+ maUpdateShapes.insert( pCurrShape );
+ }
+
+ aCurrShapeEntry->second = rCurrWeakLayer;
+ }
+
+ // update layerbounds regardless of the fact that the
+ // shape might be contained in said layer
+ // already. updateBounds() is dumb and needs to
+ // collect all shape bounds.
+ // of course, no need to expand layer bounds for
+ // shapes that reside in sprites themselves.
+ if( !bThisIsBackgroundDetached && !bIsBackgroundLayer )
+ rCurrLayer->updateBounds( pCurrShape );
+
+ bLastWasBackgroundDetached = bThisIsBackgroundDetached;
+ ++aCurrShapeEntry;
+ }
+
+ // commit very last layer data
+ commitLayerChanges(nCurrLayerIndex,
+ aCurrLayerFirstShapeEntry,
+ aCurrShapeEntry);
+
+ // any layers left? Bin them!
+ if( maLayers.size() > nCurrLayerIndex+1 )
+ maLayers.erase(maLayers.begin()+nCurrLayerIndex+1,
+ maLayers.end());
+
+ mbLayerAssociationDirty = false;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/layermanager.hxx b/slideshow/source/engine/slide/layermanager.hxx
new file mode 100644
index 000000000000..cf5e01329c4a
--- /dev/null
+++ b/slideshow/source/engine/slide/layermanager.hxx
@@ -0,0 +1,388 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_LAYERMANAGER_HXX
+#define INCLUDED_SLIDESHOW_LAYERMANAGER_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <cppcanvas/spritecanvas.hxx>
+
+#include "unoview.hxx"
+#include "unoviewcontainer.hxx"
+#include "attributableshape.hxx"
+#include "layer.hxx"
+#include "tools.hxx"
+
+#include <vector>
+#include <map>
+#include <hash_map>
+#include <algorithm>
+#include <functional>
+
+namespace basegfx {
+ class B2DRange;
+}
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /* Definition of Layermanager class */
+
+ /** This class manages all of a slide's layers (and shapes)
+
+ Since layer content changes when animations start or end,
+ the layer manager keeps track of this and also handles
+ starting/stopping of Shape animations. Note that none of
+ the methods actually perform a screen update, this is
+ always delayed until the ActivitiesQueue explicitely
+ performs it.
+
+ @see Layer
+ @see Shape
+ */
+ class LayerManager : private boost::noncopyable
+ {
+ public:
+ /** Create a new layer manager for the given page bounds
+
+ @param rViews
+ Views currently registered
+
+ @param rPageBounds
+ Overall page bounds, in user space coordinates
+
+ @param bDisableAnimationZOrder
+ When true, all sprite animations run in the
+ foreground. That is, no extra layers are created, and
+ the slideshow runs potentially faster.
+ */
+ LayerManager( const UnoViewContainer& rViews,
+ const ::basegfx::B2DRange& rPageBounds,
+ bool bDisableAnimationZOrder );
+
+ /** Activate the LayerManager
+
+ This method activates the LayerManager. Prior to
+ activation, this instance will be passive, i.e. won't
+ render anything to any view.
+
+ @param bSlideBackgoundPainted
+ When true, the initial slide content on the background
+ layer is already rendered (e.g. from a previous slide
+ transition). When false, LayerManager also renders
+ initial content of background layer on next update()
+ call.
+ */
+ void activate( bool bSlideBackgoundPainted );
+
+ /** Deactivate the LayerManager
+
+ This method deactivates the LayerManager. After
+ deactivation, this instance will be passive,
+ i.e. don't render anything to any view. Furthermore,
+ if there's currently more than one Layer active, this
+ method also removes all but one.
+ */
+ void deactivate();
+
+ // From ViewEventHandler, forwarded by SlideImpl
+ /// Notify new view added to UnoViewContainer
+ void viewAdded( const UnoViewSharedPtr& rView );
+ /// Notify view removed from UnoViewContainer
+ void viewRemoved( const UnoViewSharedPtr& rView );
+ void viewChanged( const UnoViewSharedPtr& rView );
+ void viewsChanged();
+
+ /** Add the shape to this object
+
+ This method adds a shape to the page.
+ */
+ void addShape( const ShapeSharedPtr& rShape );
+
+ /** Remove shape from this object
+
+ This method removes a shape from the shape.
+ */
+ bool removeShape( const ShapeSharedPtr& rShape );
+
+ /** Lookup a Shape from an XShape model object
+
+ This method looks up the internal shape map for one
+ representing the given XShape.
+
+ @param xShape
+ The XShape object, for which the representing Shape
+ should be looked up.
+ */
+ ShapeSharedPtr lookupShape( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape ) const;
+
+ /** Query a subset of the given original shape
+
+ This method queries a new (but not necessarily unique)
+ shape, which displays only the given subset of the
+ original one.
+ */
+ AttributableShapeSharedPtr getSubsetShape( const AttributableShapeSharedPtr& rOrigShape,
+ const DocTreeNode& rTreeNode );
+
+ /** Revoke a previously queried subset shape.
+
+ With this method, a previously requested subset shape
+ is revoked again. If the last client revokes a given
+ subset, it will cease to be displayed, and the
+ original shape will again show the subset data.
+
+ @param rOrigShape
+ The shape the subset was created from
+
+ @param rSubsetShape
+ The subset created from rOrigShape
+ */
+ void revokeSubset( const AttributableShapeSharedPtr& rOrigShape,
+ const AttributableShapeSharedPtr& rSubsetShape );
+
+ /** Notify the LayerManager that the given Shape starts an
+ animation now.
+
+ This method enters animation mode for the Shape on all
+ registered views.
+ */
+ void enterAnimationMode( const AnimatableShapeSharedPtr& rShape );
+
+ /** Notify the LayerManager that the given Shape is no
+ longer animated.
+
+ This methods ends animation mode for the given Shape
+ on all registered views.
+ */
+ void leaveAnimationMode( const AnimatableShapeSharedPtr& rShape );
+
+ /** Notify that a shape needs an update
+
+ This method notifies the layer manager that a shape
+ update is necessary. This is useful if, during
+ animation playback, changes occur to shapes which make
+ an update necessary on an update() call. Otherwise,
+ update() will not render anything, which is not
+ triggered by calling one of the other LayerManager
+ methods.
+
+ @param rShape
+ Shape which needs an update
+ */
+ void notifyShapeUpdate( const ShapeSharedPtr& rShape);
+
+ /** Check whether any update operations are pending.
+
+ @return true, if this LayerManager has any updates
+ pending, i.e. needs to repaint something for the next
+ frame.
+ */
+ bool isUpdatePending() const;
+
+ /** Update the content
+
+ This method updates the content on all layers on all
+ registered views. It does not issues a
+ View::updateScreen() call on registered views. Please
+ note that this method only takes into account changes
+ to shapes induced directly by calling methods of the
+ LayerManager. If a shape needs an update, because of
+ some external event unknown to the LayerManager (most
+ notably running animations), you have to notify the
+ LayerManager via notifyShapeUpdate().
+
+ @see LayerManager::updateScreen()
+
+ @return whether the update finished successfully.
+ */
+ bool update();
+
+ /** Render the content to given canvas
+
+ This is a one-shot operation, which simply draws all
+ shapes onto the given canvas, without any caching or
+ other fuzz. Don't use that for repeated output onto
+ the same canvas, the View concept is more optimal
+ then.
+
+ @param rTargetCanvas
+ Target canvas to output onto.
+ */
+ bool renderTo( const ::cppcanvas::CanvasSharedPtr& rTargetCanvas ) const;
+
+ private:
+ /** A hash map which maps the XShape to the corresponding Shape object.
+
+ Provides quicker lookup than ShapeSet for simple mappings
+ */
+ typedef ::std::hash_map<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >,
+ ShapeSharedPtr,
+ hash< ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > > > XShapeHash;
+
+ class ShapeComparator
+ {
+ public:
+ bool operator() (const ShapeSharedPtr& rpS1, const ShapeSharedPtr& rpS2 ) const
+ {
+ return Shape::lessThanShape::compare(rpS1.get(), rpS2.get());
+ }
+ };
+ /** Set of all shapes
+ */
+ private:
+ typedef ::std::map< ShapeSharedPtr, LayerWeakPtr, ShapeComparator > LayerShapeMap;
+ typedef ::std::set< ShapeSharedPtr > ShapeUpdateSet;
+
+
+ ////////////////////////////////////////////////////////////////////////
+
+
+ /// Adds shape area to containing layer's damage area
+ void addUpdateArea( ShapeSharedPtr const& rShape );
+
+ LayerSharedPtr createForegroundLayer() const;
+
+ /** Push changes from updateShapeLayerAssociations() to current layer
+
+ Factored-out method that resizes layer, if necessary,
+ assigns correct layer priority, and repaints contained shapes.
+
+ @param nCurrLayerIndex
+ Index of current layer in maLayers
+
+ @param aFirstLayerShape
+ Valid iterator out of maAllShapes, denoting the first
+ shape from nCurrLayerIndex
+
+ @param aEndLayerShapes
+ Valid iterator or end iterator out of maAllShapes,
+ denoting one-behind-the-last shape of nCurrLayerIndex
+ */
+ void commitLayerChanges( std::size_t nCurrLayerIndex,
+ LayerShapeMap::const_iterator aFirstLayerShape,
+ LayerShapeMap::const_iterator aEndLayerShapes );
+
+ /** Init Shape layers with background layer.
+ */
+ void putShape2BackgroundLayer( LayerShapeMap::value_type& rShapeEntry );
+
+ /** Commits any pending layer reorg, due to shapes either
+ entering or leaving animation mode
+
+ @param bBackgroundLayerPainted
+ When true, LayerManager does not render anything on
+ the background layer. Use this, if background has been
+ updated by other means (e.g. slide transition)
+ */
+ void updateShapeLayers( bool bBackgroundLayerPainted );
+
+ /** Common stuff when adding a shape
+ */
+ void implAddShape( const ShapeSharedPtr& rShape );
+
+ /** Common stuff when removing a shape
+ */
+ void implRemoveShape( const ShapeSharedPtr& rShape );
+
+ /** Add or remove views
+
+ Sharing duplicate code from viewAdded and viewRemoved
+ method. The only point of variation at those places
+ are removal vs. adding.
+ */
+ template<typename LayerFunc,
+ typename ShapeFunc> void manageViews( LayerFunc layerFunc,
+ ShapeFunc shapeFunc );
+
+ bool updateSprites();
+
+ /// Registered views
+ const UnoViewContainer& mrViews;
+
+ /// All layers of this object. Vector owns the layers
+ LayerVector maLayers;
+
+ /** Contains all shapes with their XShape reference as the key
+ */
+ XShapeHash maXShapeHash;
+
+ /** Set of shapes this LayerManager own
+
+ Contains the same set of shapes as XShapeHash, but is
+ sorted in z order, for painting and layer
+ association. Set entries are enriched with two flags
+ for buffering animation enable/disable changes, and
+ shape update requests.
+ */
+ LayerShapeMap maAllShapes;
+
+ /** Set of shapes that have requested an update
+
+ When a shape is member of this set, its maShapes entry
+ has bNeedsUpdate set to true. We maintain this
+ redundant information for faster update processing.
+ */
+ ShapeUpdateSet maUpdateShapes;
+
+ /** Overall slide bounds (in user coordinate
+ system). shapes that exceed this boundary are clipped,
+ thus, layers only need to be of this size.
+ */
+ const basegfx::B2DRange maPageBounds;
+
+ /// Number of shape sprites currenly active on this LayerManager
+ sal_Int32 mnActiveSprites;
+
+ /// TRUE, if shapes might need to move to different layer
+ bool mbLayerAssociationDirty;
+
+ /// FALSE when deactivated
+ bool mbActive;
+
+ /** When true, all sprite animations run in the foreground. That
+ is, no extra layers are created, and the slideshow runs
+ potentially faster.
+ */
+ bool mbDisableAnimationZOrder;
+ };
+
+ typedef ::boost::shared_ptr< LayerManager > LayerManagerSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_LAYERMANAGER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/makefile.mk b/slideshow/source/engine/slide/makefile.mk
new file mode 100644
index 000000000000..953307d621c1
--- /dev/null
+++ b/slideshow/source/engine/slide/makefile.mk
@@ -0,0 +1,51 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=slideshow
+TARGET=slide
+ENABLE_EXCEPTIONS=TRUE
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Common ----------------------------------------------------------
+
+SLOFILES = $(SLO)$/layer.obj \
+ $(SLO)$/layermanager.obj \
+ $(SLO)$/shapemanagerimpl.obj \
+ $(SLO)$/slideanimations.obj \
+ $(SLO)$/slideimpl.obj \
+ $(SLO)$/userpaintoverlay.obj
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/slide/shapemanagerimpl.cxx b/slideshow/source/engine/slide/shapemanagerimpl.cxx
new file mode 100644
index 000000000000..bc185689024b
--- /dev/null
+++ b/slideshow/source/engine/slide/shapemanagerimpl.cxx
@@ -0,0 +1,464 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/presentation/XShapeEventListener.hpp>
+#include <com/sun/star/presentation/XSlideShowListener.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+
+#include "shapemanagerimpl.hxx"
+
+#include <boost/bind.hpp>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer& rMultiplexer,
+ LayerManagerSharedPtr const& rLayerManager,
+ CursorManager& rCursorManager,
+ const ShapeEventListenerMap& rGlobalListenersMap,
+ const ShapeCursorMap& rGlobalCursorMap ):
+ mrMultiplexer(rMultiplexer),
+ mpLayerManager(rLayerManager),
+ mrCursorManager(rCursorManager),
+ mrGlobalListenersMap(rGlobalListenersMap),
+ mrGlobalCursorMap(rGlobalCursorMap),
+ maShapeListenerMap(),
+ maShapeCursorMap(),
+ maHyperlinkShapes(),
+ mbEnabled(false)
+{
+}
+
+void ShapeManagerImpl::activate( bool bSlideBackgoundPainted )
+{
+ if( !mbEnabled )
+ {
+ mbEnabled = true;
+
+ // register this handler on EventMultiplexer.
+ // Higher prio (overrides other engine handlers)
+ mrMultiplexer.addMouseMoveHandler( shared_from_this(), 2.0 );
+ mrMultiplexer.addClickHandler( shared_from_this(), 2.0 );
+ mrMultiplexer.addShapeListenerHandler( shared_from_this() );
+
+ // clone listener map
+ uno::Reference<presentation::XShapeEventListener> xDummyListener;
+ std::for_each( mrGlobalListenersMap.begin(),
+ mrGlobalListenersMap.end(),
+ boost::bind( &ShapeManagerImpl::listenerAdded,
+ this,
+ boost::cref(xDummyListener),
+ boost::bind(
+ std::select1st<ShapeEventListenerMap::value_type>(),
+ _1 )));
+
+ // clone cursor map
+ std::for_each( mrGlobalCursorMap.begin(),
+ mrGlobalCursorMap.end(),
+ boost::bind( &ShapeManagerImpl::cursorChanged,
+ this,
+ boost::bind(
+ std::select1st<ShapeCursorMap::value_type>(),
+ _1 ),
+ boost::bind(
+ std::select2nd<ShapeCursorMap::value_type>(),
+ _1 )));
+
+ if( mpLayerManager )
+ mpLayerManager->activate( bSlideBackgoundPainted );
+ }
+}
+
+void ShapeManagerImpl::deactivate()
+{
+ if( mbEnabled )
+ {
+ mbEnabled = false;
+
+ if( mpLayerManager )
+ mpLayerManager->deactivate();
+
+ maShapeListenerMap.clear();
+ maShapeCursorMap.clear();
+
+ mrMultiplexer.removeShapeListenerHandler( shared_from_this() );
+ mrMultiplexer.removeMouseMoveHandler( shared_from_this() );
+ mrMultiplexer.removeClickHandler( shared_from_this() );
+ }
+}
+
+void ShapeManagerImpl::dispose()
+{
+ // remove listeners (EventMultiplexer holds shared_ptr on us)
+ deactivate();
+
+ maHyperlinkShapes.clear();
+ maShapeCursorMap.clear();
+ maShapeListenerMap.clear();
+ mpLayerManager.reset();
+}
+
+bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent const& )
+{
+ // not used here
+ return false; // did not handle the event
+}
+
+bool ShapeManagerImpl::handleMouseReleased( awt::MouseEvent const& e )
+{
+ if( !mbEnabled || e.Buttons != awt::MouseButton::LEFT)
+ return false;
+
+ basegfx::B2DPoint const aPosition( e.X, e.Y );
+
+ // first check for hyperlinks, because these have
+ // highest prio:
+ rtl::OUString const hyperlink( checkForHyperlink(aPosition) );
+ if( hyperlink.getLength() > 0 )
+ {
+ mrMultiplexer.notifyHyperlinkClicked(hyperlink);
+ return true; // event consumed
+ }
+
+ // find matching shape (scan reversely, to coarsely match
+ // paint order)
+ ShapeToListenersMap::reverse_iterator aCurrBroadcaster(
+ maShapeListenerMap.rbegin() );
+ ShapeToListenersMap::reverse_iterator const aEndBroadcasters(
+ maShapeListenerMap.rend() );
+ while( aCurrBroadcaster != aEndBroadcasters )
+ {
+ // TODO(F2): Get proper geometry polygon from the
+ // shape, to avoid having areas outside the shape
+ // react on the mouse
+ if( aCurrBroadcaster->first->getBounds().isInside( aPosition ) &&
+ aCurrBroadcaster->first->isVisible() )
+ {
+ // shape hit, and shape is visible. Raise
+ // event.
+
+ boost::shared_ptr<cppu::OInterfaceContainerHelper> const pCont(
+ aCurrBroadcaster->second );
+ uno::Reference<drawing::XShape> const xShape(
+ aCurrBroadcaster->first->getXShape() );
+
+ // DON'T do anything with /this/ after this point!
+ pCont->forEach<presentation::XShapeEventListener>(
+ boost::bind( &presentation::XShapeEventListener::click,
+ _1,
+ boost::cref(xShape),
+ boost::cref(e) ));
+
+ return true; // handled this event
+ }
+
+ ++aCurrBroadcaster;
+ }
+
+ return false; // did not handle this event
+}
+
+bool ShapeManagerImpl::handleMouseEntered( const awt::MouseEvent& )
+{
+ // not used here
+ return false; // did not handle the event
+}
+
+bool ShapeManagerImpl::handleMouseExited( const awt::MouseEvent& )
+{
+ // not used here
+ return false; // did not handle the event
+}
+
+bool ShapeManagerImpl::handleMouseDragged( const awt::MouseEvent& )
+{
+ // not used here
+ return false; // did not handle the event
+}
+
+bool ShapeManagerImpl::handleMouseMoved( const awt::MouseEvent& e )
+{
+ if( !mbEnabled )
+ return false;
+
+ // find hit shape in map
+ const ::basegfx::B2DPoint aPosition( e.X, e.Y );
+ sal_Int16 nNewCursor(-1);
+
+ if( checkForHyperlink(aPosition).getLength() > 0 )
+ {
+ nNewCursor = awt::SystemPointer::REFHAND;
+ }
+ else
+ {
+ // find matching shape (scan reversely, to coarsely match
+ // paint order)
+ ShapeToCursorMap::reverse_iterator aCurrCursor(
+ maShapeCursorMap.rbegin() );
+ ShapeToCursorMap::reverse_iterator const aEndCursors(
+ maShapeCursorMap.rend() );
+ while( aCurrCursor != aEndCursors )
+ {
+ // TODO(F2): Get proper geometry polygon from the
+ // shape, to avoid having areas outside the shape
+ // react on the mouse
+ if( aCurrCursor->first->getBounds().isInside( aPosition ) &&
+ aCurrCursor->first->isVisible() )
+ {
+ // shape found, and it's visible. set
+ // requested cursor to shape's
+ nNewCursor = aCurrCursor->second;
+ break;
+ }
+
+ ++aCurrCursor;
+ }
+ }
+
+ if( nNewCursor == -1 )
+ mrCursorManager.resetCursor();
+ else
+ mrCursorManager.requestCursor( nNewCursor );
+
+ return false; // we don't /eat/ this event. Lower prio
+ // handler should see it, too.
+}
+
+bool ShapeManagerImpl::update()
+{
+ if( mbEnabled && mpLayerManager )
+ return mpLayerManager->update();
+
+ return false;
+}
+
+bool ShapeManagerImpl::update( ViewSharedPtr const& /*rView*/ )
+{
+ // am not doing view-specific updates here.
+ return false;
+}
+
+bool ShapeManagerImpl::needsUpdate() const
+{
+ if( mbEnabled && mpLayerManager )
+ return mpLayerManager->isUpdatePending();
+
+ return false;
+}
+
+void ShapeManagerImpl::enterAnimationMode( const AnimatableShapeSharedPtr& rShape )
+{
+ if( mbEnabled && mpLayerManager )
+ mpLayerManager->enterAnimationMode(rShape);
+}
+
+void ShapeManagerImpl::leaveAnimationMode( const AnimatableShapeSharedPtr& rShape )
+{
+ if( mbEnabled && mpLayerManager )
+ mpLayerManager->leaveAnimationMode(rShape);
+}
+
+void ShapeManagerImpl::notifyShapeUpdate( const ShapeSharedPtr& rShape )
+{
+ if( mbEnabled && mpLayerManager )
+ mpLayerManager->notifyShapeUpdate(rShape);
+}
+
+ShapeSharedPtr ShapeManagerImpl::lookupShape( uno::Reference< drawing::XShape > const & xShape ) const
+{
+ if( mpLayerManager )
+ return mpLayerManager->lookupShape(xShape);
+
+ return ShapeSharedPtr();
+}
+
+void ShapeManagerImpl::addHyperlinkArea( const HyperlinkAreaSharedPtr& rArea )
+{
+ maHyperlinkShapes.insert(rArea);
+}
+
+void ShapeManagerImpl::removeHyperlinkArea( const HyperlinkAreaSharedPtr& rArea )
+{
+ maHyperlinkShapes.erase(rArea);
+}
+
+AttributableShapeSharedPtr ShapeManagerImpl::getSubsetShape( const AttributableShapeSharedPtr& rOrigShape,
+ const DocTreeNode& rTreeNode )
+{
+ if( mpLayerManager )
+ return mpLayerManager->getSubsetShape(rOrigShape,rTreeNode);
+
+ return AttributableShapeSharedPtr();
+}
+
+void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr& rOrigShape,
+ const AttributableShapeSharedPtr& rSubsetShape )
+{
+ if( mpLayerManager )
+ mpLayerManager->revokeSubset(rOrigShape,rSubsetShape);
+}
+
+bool ShapeManagerImpl::listenerAdded(
+ const uno::Reference<presentation::XShapeEventListener>& /*xListener*/,
+ const uno::Reference<drawing::XShape>& xShape )
+{
+ ShapeEventListenerMap::const_iterator aIter;
+ if( (aIter = mrGlobalListenersMap.find( xShape )) ==
+ mrGlobalListenersMap.end() )
+ {
+ ENSURE_OR_RETURN_FALSE(false,
+ "ShapeManagerImpl::listenerAdded(): global "
+ "shape listener map inconsistency!");
+ }
+
+ // is this one of our shapes? other shapes are ignored.
+ ShapeSharedPtr pShape( lookupShape(xShape) );
+ if( pShape )
+ {
+ maShapeListenerMap.insert(
+ ShapeToListenersMap::value_type(
+ pShape,
+ aIter->second));
+ }
+
+ return true;
+}
+
+bool ShapeManagerImpl::listenerRemoved(
+ const uno::Reference<presentation::XShapeEventListener>& /*xListener*/,
+ const uno::Reference<drawing::XShape>& xShape )
+{
+ // shape really erased from map? maybe there are other listeners
+ // for the same shape pending...
+ if( mrGlobalListenersMap.find(xShape) == mrGlobalListenersMap.end() )
+ {
+ // is this one of our shapes? other shapes are ignored.
+ ShapeSharedPtr pShape( lookupShape(xShape) );
+ if( pShape )
+ maShapeListenerMap.erase(pShape);
+ }
+
+ return true;
+}
+
+bool ShapeManagerImpl::cursorChanged( const uno::Reference<drawing::XShape>& xShape,
+ sal_Int16 nCursor )
+{
+ ShapeSharedPtr pShape( lookupShape(xShape) );
+
+ // is this one of our shapes? other shapes are ignored.
+ if( !pShape )
+ return false;
+
+ if( mrGlobalCursorMap.find(xShape) == mrGlobalCursorMap.end() )
+ {
+ // erased from global map - erase locally, too
+ maShapeCursorMap.erase(pShape);
+ }
+ else
+ {
+ // included in global map - update local one
+ ShapeToCursorMap::iterator aIter;
+ if( (aIter = maShapeCursorMap.find(pShape))
+ == maShapeCursorMap.end() )
+ {
+ maShapeCursorMap.insert(
+ ShapeToCursorMap::value_type(
+ pShape,
+ nCursor ));
+ }
+ else
+ {
+ aIter->second = nCursor;
+ }
+ }
+
+ return true;
+}
+
+rtl::OUString ShapeManagerImpl::checkForHyperlink( basegfx::B2DPoint const& hitPos ) const
+{
+ // find matching region (scan reversely, to coarsely match
+ // paint order): set is ordered by priority
+ AreaSet::const_reverse_iterator iPos( maHyperlinkShapes.rbegin() );
+ AreaSet::const_reverse_iterator const iEnd( maHyperlinkShapes.rend() );
+ for( ; iPos != iEnd; ++iPos )
+ {
+ HyperlinkAreaSharedPtr const& pArea = *iPos;
+
+ HyperlinkArea::HyperlinkRegions const linkRegions(
+ pArea->getHyperlinkRegions() );
+
+ for( std::size_t i = linkRegions.size(); i--; )
+ {
+ basegfx::B2DRange const& region = linkRegions[i].first;
+ if( region.isInside(hitPos) )
+ return linkRegions[i].second;
+ }
+ }
+
+ return rtl::OUString();
+}
+
+void ShapeManagerImpl::addIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler )
+{
+ maIntrinsicAnimationEventHandlers.add( rHandler );
+}
+
+void ShapeManagerImpl::removeIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler )
+{
+ maIntrinsicAnimationEventHandlers.remove( rHandler );
+}
+
+bool ShapeManagerImpl::notifyIntrinsicAnimationsEnabled()
+{
+ return maIntrinsicAnimationEventHandlers.applyAll(
+ boost::mem_fn(&IntrinsicAnimationEventHandler::enableAnimations));
+}
+
+bool ShapeManagerImpl::notifyIntrinsicAnimationsDisabled()
+{
+ return maIntrinsicAnimationEventHandlers.applyAll(
+ boost::mem_fn(&IntrinsicAnimationEventHandler::disableAnimations));
+}
+
+
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/shapemanagerimpl.hxx b/slideshow/source/engine/slide/shapemanagerimpl.hxx
new file mode 100644
index 000000000000..cf5addcc95ad
--- /dev/null
+++ b/slideshow/source/engine/slide/shapemanagerimpl.hxx
@@ -0,0 +1,212 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_SHAPEMANAGERIMPL_HXX
+#define INCLUDED_SLIDESHOW_SHAPEMANAGERIMPL_HXX
+
+#include <osl/mutex.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <com/sun/star/presentation/XShapeEventListener.hpp>
+
+#include "shape.hxx"
+#include "subsettableshapemanager.hxx"
+#include "eventmultiplexer.hxx"
+#include "layermanager.hxx"
+#include "viewupdate.hxx"
+#include "shapemaps.hxx"
+#include "cursormanager.hxx"
+#include "hyperlinkarea.hxx"
+#include "listenercontainer.hxx"
+#include "shapelistenereventhandler.hxx"
+#include "mouseeventhandler.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/noncopyable.hpp>
+#include <set>
+#include <map>
+
+namespace slideshow {
+namespace internal {
+
+/** Listener class for shape events
+
+ This helper class registers itself on each view, and
+ broadcasts the XShapeEventListener events. The mouse motion
+ events are needed for setting the shape cursor.
+*/
+class ShapeManagerImpl : public SubsettableShapeManager,
+ public ShapeListenerEventHandler,
+ public MouseEventHandler,
+ public ViewUpdate,
+ public boost::enable_shared_from_this<ShapeManagerImpl>,
+ private boost::noncopyable
+{
+public:
+ /** Create a shape event broadcaster
+
+ @param rEventMultiplexer
+ The slideshow-global event source, where this class
+ registeres its event handlers.
+ */
+ ShapeManagerImpl( EventMultiplexer& rMultiplexer,
+ LayerManagerSharedPtr const& rLayerManager,
+ CursorManager& rCursorManager,
+ const ShapeEventListenerMap& rGlobalListenersMap,
+ const ShapeCursorMap& rGlobalCursorMap );
+
+ /** Enables event listening.
+
+ @param bSlideBackgoundPainted
+ When true, the initial slide content on the background layer
+ is already rendered (e.g. from a previous slide
+ transition). When false, slide renders initial content of
+ slide.
+ */
+ void activate( bool bSlideBackgoundPainted );
+
+ /** Disables event listening.
+ */
+ void deactivate();
+
+ // Disposable interface
+ // ---------------------------------------------------------------
+
+ virtual void dispose();
+
+private:
+
+ // MouseEventHandler interface
+ // ---------------------------------------------------------------
+
+ virtual bool handleMousePressed(
+ ::com::sun::star::awt::MouseEvent const& evt );
+ virtual bool handleMouseReleased(
+ ::com::sun::star::awt::MouseEvent const& evt );
+ virtual bool handleMouseEntered(
+ ::com::sun::star::awt::MouseEvent const& evt );
+ virtual bool handleMouseExited(
+ ::com::sun::star::awt::MouseEvent const& evt );
+ virtual bool handleMouseDragged(
+ ::com::sun::star::awt::MouseEvent const& evt );
+ virtual bool handleMouseMoved(
+ ::com::sun::star::awt::MouseEvent const& evt );
+
+
+ // ViewUpdate interface
+ // -------------------------------------------------------------------
+
+ virtual bool update();
+ virtual bool update( ViewSharedPtr const& rView );
+ virtual bool needsUpdate() const;
+
+
+ // ShapeManager interface
+ // ---------------------------------------------------
+
+ virtual void enterAnimationMode( const AnimatableShapeSharedPtr& rShape );
+ virtual void leaveAnimationMode( const AnimatableShapeSharedPtr& rShape );
+ virtual void notifyShapeUpdate( const ShapeSharedPtr& rShape );
+ virtual ShapeSharedPtr lookupShape(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > const & xShape ) const;
+ virtual void addHyperlinkArea( const boost::shared_ptr<HyperlinkArea>& rArea );
+ virtual void removeHyperlinkArea( const boost::shared_ptr<HyperlinkArea>& rArea );
+
+
+ // SubsettableShapeManager interface
+ // ---------------------------------------------------
+
+ virtual boost::shared_ptr<AttributableShape> getSubsetShape(
+ const boost::shared_ptr<AttributableShape>& rOrigShape,
+ const DocTreeNode& rTreeNode );
+ virtual void revokeSubset(
+ const boost::shared_ptr<AttributableShape>& rOrigShape,
+ const boost::shared_ptr<AttributableShape>& rSubsetShape );
+
+ virtual void addIntrinsicAnimationHandler(
+ const IntrinsicAnimationEventHandlerSharedPtr& rHandler );
+ virtual void removeIntrinsicAnimationHandler(
+ const IntrinsicAnimationEventHandlerSharedPtr& rHandler );
+ virtual bool notifyIntrinsicAnimationsEnabled();
+ virtual bool notifyIntrinsicAnimationsDisabled();
+
+
+ // ShapeListenerEventHandler
+ // ---------------------------------------------
+
+ virtual bool listenerAdded( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XShapeEventListener>& xListener,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape );
+
+ virtual bool listenerRemoved( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XShapeEventListener>& xListener,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape );
+
+ // ShapeCursorEventHandler interface
+ // ---------------------------------------------------------------
+
+ virtual bool cursorChanged( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape,
+ sal_Int16 nCursor );
+
+
+ ::rtl::OUString checkForHyperlink( ::basegfx::B2DPoint const& hitPos )const;
+
+
+ typedef std::map<ShapeSharedPtr,
+ boost::shared_ptr< ::cppu::OInterfaceContainerHelper >,
+ Shape::lessThanShape> ShapeToListenersMap;
+ typedef std::map<ShapeSharedPtr, sal_Int16,
+ Shape::lessThanShape> ShapeToCursorMap;
+ typedef std::set<HyperlinkAreaSharedPtr,
+ HyperlinkArea::lessThanArea> AreaSet;
+
+ typedef ThreadUnsafeListenerContainer<
+ IntrinsicAnimationEventHandlerSharedPtr,
+ std::vector<IntrinsicAnimationEventHandlerSharedPtr> > ImplIntrinsicAnimationEventHandlers;
+
+ EventMultiplexer& mrMultiplexer;
+ LayerManagerSharedPtr mpLayerManager;
+ CursorManager& mrCursorManager;
+ const ShapeEventListenerMap& mrGlobalListenersMap;
+ const ShapeCursorMap& mrGlobalCursorMap;
+ ShapeToListenersMap maShapeListenerMap;
+ ShapeToCursorMap maShapeCursorMap;
+ AreaSet maHyperlinkShapes;
+ ImplIntrinsicAnimationEventHandlers maIntrinsicAnimationEventHandlers;
+ bool mbEnabled;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_SHAPEMANAGERIMPL_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/slideanimations.cxx b/slideshow/source/engine/slide/slideanimations.cxx
new file mode 100644
index 000000000000..0e459a8127d3
--- /dev/null
+++ b/slideshow/source/engine/slide/slideanimations.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/diagnose_ex.h>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include "slideanimations.hxx"
+#include "animationnodefactory.hxx"
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ SlideAnimations::SlideAnimations( const SlideShowContext& rContext,
+ const ::basegfx::B2DVector& rSlideSize ) :
+ maContext( rContext ),
+ maSlideSize( rSlideSize ),
+ mpRootNode()
+ {
+ ENSURE_OR_THROW( maContext.mpSubsettableShapeManager,
+ "SlideAnimations::SlideAnimations(): Invalid SlideShowContext" );
+ }
+
+ SlideAnimations::~SlideAnimations()
+ {
+ if( mpRootNode )
+ {
+ SHOW_NODE_TREE( mpRootNode );
+
+ try
+ {
+ mpRootNode->dispose();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ }
+
+ bool SlideAnimations::importAnimations( const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
+ {
+ mpRootNode = AnimationNodeFactory::createAnimationNode(
+ xRootAnimationNode,
+ maSlideSize,
+ maContext );
+
+ SHOW_NODE_TREE( mpRootNode );
+
+ return mpRootNode;
+ }
+
+ bool SlideAnimations::isAnimated() const
+ {
+ if( !mpRootNode )
+ return false; // no animations there
+
+ // query root node about pending animations
+ return mpRootNode->hasPendingAnimation();
+ }
+
+ bool SlideAnimations::start()
+ {
+ if( !mpRootNode )
+ return false; // no animations there
+
+ // init all nodes
+ if( !mpRootNode->init() )
+ return false;
+
+ // resolve root node
+ if( !mpRootNode->resolve() )
+ return false;
+
+ return true;
+ }
+
+ void SlideAnimations::end()
+ {
+ if( !mpRootNode )
+ return; // no animations there
+
+ // end root node
+ mpRootNode->deactivate();
+ mpRootNode->end();
+ }
+
+ void SlideAnimations::dispose()
+ {
+ mpRootNode.reset();
+ maContext.dispose();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/slideanimations.hxx b/slideshow/source/engine/slide/slideanimations.hxx
new file mode 100644
index 000000000000..02bc38fd8c6d
--- /dev/null
+++ b/slideshow/source/engine/slide/slideanimations.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SLIDEANIMATIONS_HXX
+#define INCLUDED_SLIDESHOW_SLIDEANIMATIONS_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <basegfx/vector/b2dvector.hxx>
+
+#include "event.hxx"
+#include "slideshowcontext.hxx"
+#include "subsettableshapemanager.hxx"
+#include "animationnode.hxx"
+
+namespace com { namespace sun { namespace star { namespace animations
+{
+ class XAnimationNode;
+} } } }
+
+
+/* Definition of SlideAnimations class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class generates and manages all animations of a slide.
+
+ Provided with the root animation node, this class imports
+ the effect information and builds the event tree for all
+ of the slide's animations.
+ */
+ class SlideAnimations
+ {
+ public:
+ /** Create an animation generator.
+
+ @param rContext
+ Slide show context, passing on common parameters
+ */
+ SlideAnimations( const SlideShowContext& rContext,
+ const ::basegfx::B2DVector& rSlideSize );
+ ~SlideAnimations();
+
+ /** Import animations from a SMIL root animation node.
+
+ This method might take some time, depending on the
+ complexity of the SMIL animation network to be
+ imported.
+
+ @param xRootAnimationNode
+ Root animation node for the effects to be
+ generated. This is typically obtained from the
+ XDrawPage's XAnimationNodeSupplier.
+
+ */
+ bool importAnimations( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xRootAnimationNode );
+
+ /** Check, whether imported animations actually contain
+ any effects.
+
+ @return true, if there are actual animations in the
+ imported node tree.
+ */
+ bool isAnimated() const;
+
+ /** Start the animations.
+
+ This method creates the network of events and
+ activities for all animations. The events and
+ activities are inserted into the constructor-provided
+ queues. These queues are not explicitely cleared, if
+ you rely on this object's effects to run without
+ interference, you should clear the queues by yourself.
+
+ @return true, if all events have been successfully
+ created.
+ */
+ bool start();
+
+ /** End all animations.
+
+ This method force-ends all animations. If a slide end
+ event has been registered, that is fired, too.
+ */
+ void end();
+
+ /// Release all references. Does not notify anything.
+ void dispose();
+
+ private:
+ SlideShowContext maContext;
+ const basegfx::B2DVector maSlideSize;
+ AnimationNodeSharedPtr mpRootNode;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SLIDEANIMATIONS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/slideimpl.cxx b/slideshow/source/engine/slide/slideimpl.cxx
new file mode 100644
index 000000000000..ba6cee363a04
--- /dev/null
+++ b/slideshow/source/engine/slide/slideimpl.cxx
@@ -0,0 +1,1286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <osl/diagnose.hxx>
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/canvastools.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/drawing/XMasterPageTarget.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/presentation/ParagraphTarget.hpp>
+#include <com/sun/star/presentation/EffectNodeType.hpp>
+#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
+#include <com/sun/star/animations/XTargetPropertiesCreator.hpp>
+#include <com/sun/star/drawing/TextAnimationKind.hpp>
+
+#include <animations/animationnodehelper.hxx>
+
+#include <cppuhelper/exc_hlp.hxx>
+#include <comphelper/anytostring.hxx>
+
+#include "slide.hxx"
+#include "slideshowcontext.hxx"
+#include "slideanimations.hxx"
+#include "doctreenode.hxx"
+#include "screenupdater.hxx"
+#include "cursormanager.hxx"
+#include "shapeimporter.hxx"
+#include "slideshowexceptions.hxx"
+#include "eventqueue.hxx"
+#include "activitiesqueue.hxx"
+#include "layermanager.hxx"
+#include "shapemanagerimpl.hxx"
+#include "usereventqueue.hxx"
+#include "userpaintoverlay.hxx"
+#include "event.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+#include <iterator>
+#include <algorithm>
+#include <functional>
+#include <iostream>
+
+using namespace ::com::sun::star;
+
+// -----------------------------------------------------------------------------
+
+namespace slideshow
+{
+namespace internal
+{
+namespace
+{
+
+class SlideImpl : public Slide,
+ public CursorManager,
+ public ViewEventHandler,
+ protected ::osl::DebugBase<SlideImpl>
+{
+public:
+ SlideImpl( const uno::Reference<drawing::XDrawPage>& xDrawPage,
+ const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
+ const uno::Reference<animations::XAnimationNode>& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ const PolyPolygonVector& rPolyPolygonVector,
+ RGBColor const& rUserPaintColor,
+ double dUserPaintStrokeWidth,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder );
+
+ ~SlideImpl();
+
+
+ // Disposable interface
+ // -------------------------------------------------------------------
+
+ virtual void dispose();
+
+
+ // Slide interface
+ // -------------------------------------------------------------------
+
+ virtual bool prefetch();
+ virtual bool show( bool );
+ virtual void hide();
+
+ virtual basegfx::B2ISize getSlideSize() const;
+ virtual uno::Reference<drawing::XDrawPage > getXDrawPage() const;
+ virtual uno::Reference<animations::XAnimationNode> getXAnimationNode() const;
+ virtual PolyPolygonVector getPolygons();
+ virtual void drawPolygons() const;
+ virtual bool isPaintOverlayActive() const;
+
+ // TODO(F2): Rework SlideBitmap to no longer be based on XBitmap,
+ // but on canvas-independent basegfx bitmaps
+ virtual SlideBitmapSharedPtr getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const;
+
+
+private:
+ // ViewEventHandler
+ virtual void viewAdded( const UnoViewSharedPtr& rView );
+ virtual void viewRemoved( const UnoViewSharedPtr& rView );
+ virtual void viewChanged( const UnoViewSharedPtr& rView );
+ virtual void viewsChanged();
+
+ // CursorManager
+ virtual bool requestCursor( sal_Int16 nCursorShape );
+ virtual void resetCursor();
+
+ /** Query whether the slide has animations at all
+
+ If the slide doesn't have animations, show() displays
+ only static content. If an event is registered with
+ registerSlideEndEvent(), this event will be
+ immediately activated at the end of the show() method.
+
+ @return true, if this slide has animations, false
+ otherwise
+ */
+ bool isAnimated();
+
+ /** Query whether this slide is currently showing.
+
+ @return true, if this slide is currently showing.
+ */
+ bool isShowing() const;
+
+ void enablePaintOverlay();
+ void disablePaintOverlay();
+
+ /// Set all Shapes to their initial attributes for slideshow
+ bool applyInitialShapeAttributes( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xRootAnimationNode );
+
+ /// Renders current slide content to bitmap
+ SlideBitmapSharedPtr createCurrentSlideBitmap(
+ const UnoViewSharedPtr& rView,
+ ::basegfx::B2ISize const & rSlideSize ) const;
+
+ /// Prefetch all shapes (not the animations)
+ bool loadShapes();
+
+ /// Retrieve slide size from XDrawPage
+ basegfx::B2ISize getSlideSizeImpl() const;
+
+ /// Prefetch show, but don't call applyInitialShapeAttributes()
+ bool implPrefetchShow();
+
+ /// Query the rectangle covered by the slide
+ ::basegfx::B2DRectangle getSlideRect() const;
+
+ /// Start GIF and other intrinsic shape animations
+ void endIntrinsicAnimations();
+
+ /// End GIF and other intrinsic shape animations
+ void startIntrinsicAnimations();
+
+ /// Add Polygons to the member maPolygons
+ void addPolygons(PolyPolygonVector aPolygons);
+
+ // Types
+ // =====
+
+ enum SlideAnimationState
+ {
+ CONSTRUCTING_STATE=0,
+ INITIAL_STATE=1,
+ SHOWING_STATE=2,
+ FINAL_STATE=3,
+ SlideAnimationState_NUM_ENTRIES=4
+ };
+
+ typedef std::vector< SlideBitmapSharedPtr > VectorOfSlideBitmaps;
+ /** Vector of slide bitmaps.
+
+ Since the bitmap content is sensitive to animation
+ effects, we have an inner vector containing a distinct
+ bitmap for each of the SlideAnimationStates.
+ */
+ typedef ::std::vector< std::pair< UnoViewSharedPtr,
+ VectorOfSlideBitmaps > > VectorOfVectorOfSlideBitmaps;
+
+
+ // Member variables
+ // ================
+
+ /// The page model object
+ uno::Reference< drawing::XDrawPage > mxDrawPage;
+ uno::Reference< drawing::XDrawPagesSupplier > mxDrawPagesSupplier;
+ uno::Reference< animations::XAnimationNode > mxRootNode;
+
+ LayerManagerSharedPtr mpLayerManager;
+ boost::shared_ptr<ShapeManagerImpl> mpShapeManager;
+ boost::shared_ptr<SubsettableShapeManager> mpSubsettableShapeManager;
+
+ /// Contains common objects needed throughout the slideshow
+ SlideShowContext maContext;
+
+ /// parent cursor manager
+ CursorManager& mrCursorManager;
+
+ /// Handles the animation and event generation for us
+ SlideAnimations maAnimations;
+ PolyPolygonVector maPolygons;
+
+ RGBColor maUserPaintColor;
+ double mdUserPaintStrokeWidth;
+ UserPaintOverlaySharedPtr mpPaintOverlay;
+
+ /// Bitmaps with slide content at various states
+ mutable VectorOfVectorOfSlideBitmaps maSlideBitmaps;
+
+ SlideAnimationState meAnimationState;
+
+ const basegfx::B2ISize maSlideSize;
+
+ sal_Int16 mnCurrentCursor;
+
+ /// True, when intrinsic shape animations are allowed
+ bool mbIntrinsicAnimationsAllowed;
+
+ /// True, when user paint overlay is enabled
+ bool mbUserPaintOverlayEnabled;
+
+ /// True, if initial load of all page shapes succeeded
+ bool mbShapesLoaded;
+
+ /// True, if initial load of all animation info succeeded
+ bool mbShowLoaded;
+
+ /** True, if this slide is not static.
+
+ If this slide has animated content, this variable will
+ be true, and false otherwise.
+ */
+ bool mbHaveAnimations;
+
+ /** True, if this slide has a main animation sequence.
+
+ If this slide has animation content, which in turn has
+ a main animation sequence (which must be fully run
+ before EventMultiplexer::notifySlideAnimationsEnd() is
+ called), this member is true.
+ */
+ bool mbMainSequenceFound;
+
+ /// When true, show() was called. Slide hidden oherwise.
+ bool mbActive;
+
+ ///When true, enablePaintOverlay was called and mbUserPaintOverlay = true
+ bool mbPaintOverlayActive;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+
+class SlideRenderer
+{
+public:
+ explicit SlideRenderer( SlideImpl& rSlide ) :
+ mrSlide( rSlide )
+ {
+ }
+
+ void operator()( const UnoViewSharedPtr& rView )
+ {
+ // fully clear view content to background color
+ rView->clearAll();
+
+ SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( rView ) );
+ ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
+
+ const ::basegfx::B2DHomMatrix aViewTransform( rView->getTransformation() );
+ const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
+
+ // setup a canvas with device coordinate space, the slide
+ // bitmap already has the correct dimension.
+ ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
+ pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // render at given output position
+ pBitmap->move( aOutPosPixel );
+
+ // clear clip (might have been changed, e.g. from comb
+ // transition)
+ pBitmap->clip( ::basegfx::B2DPolyPolygon() );
+ pBitmap->draw( pDevicePixelCanvas );
+ }
+
+private:
+ SlideImpl& mrSlide;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+
+SlideImpl::SlideImpl( const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
+ const uno::Reference< animations::XAnimationNode >& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference< uno::XComponentContext >& xComponentContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ const PolyPolygonVector& rPolyPolygonVector,
+ RGBColor const& aUserPaintColor,
+ double dUserPaintStrokeWidth,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder ) :
+ mxDrawPage( xDrawPage ),
+ mxDrawPagesSupplier( xDrawPages ),
+ mxRootNode( xRootNode ),
+ mpLayerManager( new LayerManager(
+ rViewContainer,
+ getSlideRect(),
+ bDisableAnimationZOrder) ),
+ mpShapeManager( new ShapeManagerImpl(
+ rEventMultiplexer,
+ mpLayerManager,
+ rCursorManager,
+ rShapeListenerMap,
+ rShapeCursorMap)),
+ mpSubsettableShapeManager( mpShapeManager ),
+ maContext( mpSubsettableShapeManager,
+ rEventQueue,
+ rEventMultiplexer,
+ rScreenUpdater,
+ rActivitiesQueue,
+ rUserEventQueue,
+ *this,
+ rViewContainer,
+ xComponentContext ),
+ mrCursorManager( rCursorManager ),
+ maAnimations( maContext,
+ getSlideSizeImpl() ),
+ maPolygons(rPolyPolygonVector),
+ maUserPaintColor(aUserPaintColor),
+ mdUserPaintStrokeWidth(dUserPaintStrokeWidth),
+ mpPaintOverlay(),
+ maSlideBitmaps(),
+ meAnimationState( CONSTRUCTING_STATE ),
+ maSlideSize(getSlideSizeImpl()),
+ mnCurrentCursor( awt::SystemPointer::ARROW ),
+ mbIntrinsicAnimationsAllowed( bIntrinsicAnimationsAllowed ),
+ mbUserPaintOverlayEnabled(bUserPaintEnabled),
+ mbShapesLoaded( false ),
+ mbShowLoaded( false ),
+ mbHaveAnimations( false ),
+ mbMainSequenceFound( false ),
+ mbActive( false ),
+ mbPaintOverlayActive( false )
+{
+ // clone already existing views for slide bitmaps
+ std::for_each( rViewContainer.begin(),
+ rViewContainer.end(),
+ boost::bind( &SlideImpl::viewAdded,
+ this,
+ _1 ));
+
+ // register screen update (LayerManager needs to signal pending
+ // updates)
+ maContext.mrScreenUpdater.addViewUpdate(mpShapeManager);
+}
+
+SlideImpl::~SlideImpl()
+{
+ if( mpShapeManager )
+ {
+ maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
+ mpShapeManager->dispose();
+
+ // TODO(Q3): Make sure LayerManager (and thus Shapes) dies
+ // first, because SlideShowContext has SubsettableShapeManager
+ // as reference member.
+ mpLayerManager.reset();
+ }
+}
+
+void SlideImpl::dispose()
+{
+ maSlideBitmaps.clear();
+ mpPaintOverlay.reset();
+ maAnimations.dispose();
+ maContext.dispose();
+
+ if( mpShapeManager )
+ {
+ maContext.mrScreenUpdater.removeViewUpdate(mpShapeManager);
+ mpShapeManager->dispose();
+ }
+
+ // TODO(Q3): Make sure LayerManager (and thus Shapes) dies first,
+ // because SlideShowContext has SubsettableShapeManager as
+ // reference member.
+ mpLayerManager.reset();
+ mpSubsettableShapeManager.reset();
+ mpShapeManager.reset();
+ mxRootNode.clear();
+ mxDrawPage.clear();
+#ifndef ENABLE_PRESENTER_EXTRA_UI
+ mxDrawPagesSupplier.clear();
+#endif
+}
+
+bool SlideImpl::prefetch()
+{
+ if( !mxRootNode.is() )
+ return false;
+
+ return applyInitialShapeAttributes(mxRootNode);
+}
+
+bool SlideImpl::show( bool bSlideBackgoundPainted )
+{
+ // ---------------------------------------------------------------
+
+ if( mbActive )
+ return true; // already active
+
+ if( !mpShapeManager || !mpLayerManager )
+ return false; // disposed
+
+ // ---------------------------------------------------------------
+
+ // set initial shape attributes (e.g. hide shapes that have
+ // 'appear' effect set)
+ if( !applyInitialShapeAttributes(mxRootNode) )
+ return false;
+
+ // ---------------------------------------------------------------
+
+ // activate and take over view - clears view, if necessary
+ mbActive = true;
+ requestCursor( mnCurrentCursor );
+
+ // enable shape management & event broadcasting for shapes of this
+ // slide. Also enables LayerManager to record updates. Currently,
+ // never let LayerManager render initial slide content, use
+ // buffered slide bitmaps instead.
+ mpShapeManager->activate( true );
+
+ // ---------------------------------------------------------------
+
+ // render slide to screen, if requested
+ if( !bSlideBackgoundPainted )
+ {
+ std::for_each(maContext.mrViewContainer.begin(),
+ maContext.mrViewContainer.end(),
+ boost::mem_fn(&View::clearAll));
+
+ std::for_each( maContext.mrViewContainer.begin(),
+ maContext.mrViewContainer.end(),
+ SlideRenderer(*this) );
+ maContext.mrScreenUpdater.notifyUpdate();
+ }
+
+ // ---------------------------------------------------------------
+
+ // fire up animations
+ const bool bIsAnimated( isAnimated() );
+ if( bIsAnimated )
+ maAnimations.start(); // feeds initial events into queue
+
+ // NOTE: this looks slightly weird, but is indeed correct:
+ // as isAnimated() might return false, _although_ there is
+ // a main sequence (because the animation nodes don't
+ // contain any executable effects), we gotta check both
+ // conditions here.
+ if( !bIsAnimated || !mbMainSequenceFound )
+ {
+ // manually trigger a slide animation end event (we don't have
+ // animations at all, or we don't have a main animation
+ // sequence, but if we had, it'd end now). Note that having
+ // animations alone does not matter here, as only main
+ // sequence animations prevents showing the next slide on
+ // nextEvent().
+ maContext.mrEventMultiplexer.notifySlideAnimationsEnd();
+ }
+
+ // enable shape-intrinsic animations (drawing layer animations or
+ // GIF animations)
+ if( mbIntrinsicAnimationsAllowed )
+ startIntrinsicAnimations();
+
+ // ---------------------------------------------------------------
+
+ // enable paint overlay, if maUserPaintColor is valid
+ enablePaintOverlay();
+
+ // ---------------------------------------------------------------
+
+ // from now on, animations might be showing
+ meAnimationState = SHOWING_STATE;
+
+ return true;
+}
+
+void SlideImpl::hide()
+{
+ if( !mbActive || !mpShapeManager )
+ return; // already hidden/disposed
+
+ // ---------------------------------------------------------------
+
+ // from now on, all animations are stopped
+ meAnimationState = FINAL_STATE;
+
+ // ---------------------------------------------------------------
+
+ // disable user paint overlay under all circumstances,
+ // this slide now ceases to be active.
+ disablePaintOverlay();
+
+ // ---------------------------------------------------------------
+
+ // switch off all shape-intrinsic animations.
+ endIntrinsicAnimations();
+
+ // force-end all SMIL animations, too
+ maAnimations.end();
+
+ // ---------------------------------------------------------------
+
+ // disable shape management & event broadcasting for shapes of this
+ // slide. Also disables LayerManager.
+ mpShapeManager->deactivate();
+
+ // vanish from view
+ resetCursor();
+ mbActive = false;
+
+ // ---------------------------------------------------------------
+}
+
+basegfx::B2ISize SlideImpl::getSlideSize() const
+{
+ return maSlideSize;
+}
+
+uno::Reference<drawing::XDrawPage > SlideImpl::getXDrawPage() const
+{
+ return mxDrawPage;
+}
+
+uno::Reference<animations::XAnimationNode> SlideImpl::getXAnimationNode() const
+{
+ return mxRootNode;
+}
+
+PolyPolygonVector SlideImpl::getPolygons()
+{
+ if(mbPaintOverlayActive)
+ maPolygons = mpPaintOverlay->getPolygons();
+ return maPolygons;
+}
+
+SlideBitmapSharedPtr SlideImpl::getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const
+{
+ // search corresponding entry in maSlideBitmaps (which
+ // contains the views as the key)
+ VectorOfVectorOfSlideBitmaps::iterator aIter;
+ const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
+ if( (aIter=std::find_if( maSlideBitmaps.begin(),
+ aEnd,
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind(
+ std::select1st<VectorOfVectorOfSlideBitmaps::value_type>(),
+ _1 )))) == aEnd )
+ {
+ // corresponding view not found - maybe view was not
+ // added to Slide?
+ ENSURE_OR_THROW( false,
+ "SlideImpl::getInitialSlideBitmap(): view does not "
+ "match any of the added ones" );
+ }
+
+ // ensure that the show is loaded
+ if( !mbShowLoaded )
+ {
+ // only prefetch and init shapes when not done already
+ // (otherwise, at least applyInitialShapeAttributes() will be
+ // called twice for initial slide rendering). Furthermore,
+ // applyInitialShapeAttributes() _always_ performs
+ // initializations, which would be highly unwanted during a
+ // running show. OTOH, a slide whose mbShowLoaded is false is
+ // guaranteed not be running a show.
+
+ // set initial shape attributes (e.g. hide 'appear' effect
+ // shapes)
+ if( !const_cast<SlideImpl*>(this)->applyInitialShapeAttributes( mxRootNode ) )
+ ENSURE_OR_THROW(false,
+ "SlideImpl::getCurrentSlideBitmap(): Cannot "
+ "apply initial attributes");
+ }
+
+ SlideBitmapSharedPtr& rBitmap( aIter->second.at( meAnimationState ));
+ const ::basegfx::B2ISize& rSlideSize(
+ getSlideSizePixel( getSlideSize(),
+ rView ));
+
+ // is the bitmap valid (actually existent, and of correct
+ // size)?
+ if( !rBitmap || rBitmap->getSize() != rSlideSize )
+ {
+ // no bitmap there yet, or wrong size - create one
+ rBitmap = createCurrentSlideBitmap(rView, rSlideSize);
+ }
+
+ return rBitmap;
+}
+
+
+// private methods
+//--------------------------------------------------------------------------------------------------------------
+
+
+void SlideImpl::viewAdded( const UnoViewSharedPtr& rView )
+{
+ maSlideBitmaps.push_back(
+ std::make_pair( rView,
+ VectorOfSlideBitmaps(SlideAnimationState_NUM_ENTRIES) ));
+
+ if( mpLayerManager )
+ mpLayerManager->viewAdded( rView );
+}
+
+void SlideImpl::viewRemoved( const UnoViewSharedPtr& rView )
+{
+ if( mpLayerManager )
+ mpLayerManager->viewRemoved( rView );
+
+ const VectorOfVectorOfSlideBitmaps::iterator aEnd( maSlideBitmaps.end() );
+ maSlideBitmaps.erase(
+ std::remove_if( maSlideBitmaps.begin(),
+ aEnd,
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind(
+ std::select1st<VectorOfVectorOfSlideBitmaps::value_type>(),
+ _1 ))),
+ aEnd );
+}
+
+void SlideImpl::viewChanged( const UnoViewSharedPtr& rView )
+{
+ // nothing to do for the Slide - getCurrentSlideBitmap() lazily
+ // handles bitmap resizes
+ if( mbActive && mpLayerManager )
+ mpLayerManager->viewChanged(rView);
+}
+
+void SlideImpl::viewsChanged()
+{
+ // nothing to do for the Slide - getCurrentSlideBitmap() lazily
+ // handles bitmap resizes
+ if( mbActive && mpLayerManager )
+ mpLayerManager->viewsChanged();
+}
+
+bool SlideImpl::requestCursor( sal_Int16 nCursorShape )
+{
+ mnCurrentCursor = nCursorShape;
+ return mrCursorManager.requestCursor(mnCurrentCursor);
+}
+
+void SlideImpl::resetCursor()
+{
+ mnCurrentCursor = awt::SystemPointer::ARROW;
+ mrCursorManager.resetCursor();
+}
+
+bool SlideImpl::isShowing() const
+{
+ return meAnimationState == SHOWING_STATE;
+}
+
+bool SlideImpl::isAnimated()
+{
+ // prefetch, but don't apply initial shape attributes
+ if( !implPrefetchShow() )
+ return false;
+
+ return mbHaveAnimations && maAnimations.isAnimated();
+}
+
+SlideBitmapSharedPtr SlideImpl::createCurrentSlideBitmap( const UnoViewSharedPtr& rView,
+ const ::basegfx::B2ISize& rBmpSize ) const
+{
+ ENSURE_OR_THROW( rView && rView->getCanvas(),
+ "SlideImpl::createCurrentSlideBitmap(): Invalid view" );
+ ENSURE_OR_THROW( mpLayerManager,
+ "SlideImpl::createCurrentSlideBitmap(): Invalid layer manager" );
+ ENSURE_OR_THROW( mbShowLoaded,
+ "SlideImpl::createCurrentSlideBitmap(): No show loaded" );
+
+ ::cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
+
+ // create a bitmap of appropriate size
+ ::cppcanvas::BitmapSharedPtr pBitmap(
+ ::cppcanvas::BaseGfxFactory::getInstance().createBitmap(
+ pCanvas,
+ rBmpSize ) );
+
+ ENSURE_OR_THROW( pBitmap,
+ "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap" );
+
+ ::cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas( pBitmap->getBitmapCanvas() );
+
+ ENSURE_OR_THROW( pBitmapCanvas,
+ "SlideImpl::createCurrentSlideBitmap(): Cannot create page bitmap canvas" );
+
+ // apply linear part of destination canvas transformation (linear means in this context:
+ // transformation without any translational components)
+ ::basegfx::B2DHomMatrix aLinearTransform( rView->getTransformation() );
+ aLinearTransform.set( 0, 2, 0.0 );
+ aLinearTransform.set( 1, 2, 0.0 );
+ pBitmapCanvas->setTransformation( aLinearTransform );
+
+ // output all shapes to bitmap
+ initSlideBackground( pBitmapCanvas, rBmpSize );
+ mpLayerManager->renderTo( pBitmapCanvas );
+
+ return SlideBitmapSharedPtr( new SlideBitmap( pBitmap ) );
+}
+
+namespace
+{
+ class MainSequenceSearcher
+ {
+ public:
+ MainSequenceSearcher()
+ {
+ maSearchKey.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
+ maSearchKey.Value <<= presentation::EffectNodeType::MAIN_SEQUENCE;
+ }
+
+ void operator()( const uno::Reference< animations::XAnimationNode >& xChildNode )
+ {
+ uno::Sequence< beans::NamedValue > aUserData( xChildNode->getUserData() );
+
+ if( findNamedValue( aUserData, maSearchKey ) )
+ {
+ maMainSequence = xChildNode;
+ }
+ }
+
+ uno::Reference< animations::XAnimationNode > getMainSequence() const
+ {
+ return maMainSequence;
+ }
+
+ private:
+ beans::NamedValue maSearchKey;
+ uno::Reference< animations::XAnimationNode > maMainSequence;
+ };
+}
+
+bool SlideImpl::implPrefetchShow()
+{
+ if( mbShowLoaded )
+ return true;
+
+ ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
+ "SlideImpl::implPrefetchShow(): Invalid draw page" );
+ ENSURE_OR_RETURN_FALSE( mpLayerManager,
+ "SlideImpl::implPrefetchShow(): Invalid layer manager" );
+
+ // fetch desired page content
+ // ==========================
+
+ if( !loadShapes() )
+ return false;
+
+ // New animations framework: import the shape effect info
+ // ======================================================
+
+ try
+ {
+ if( mxRootNode.is() )
+ {
+ if( !maAnimations.importAnimations( mxRootNode ) )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::implPrefetchShow(): have animation nodes, "
+ "but import animations failed." );
+
+ // could not import animation framework,
+ // _although_ some animation nodes are there -
+ // this is an error (not finding animations at
+ // all is okay - might be a static slide)
+ return false;
+ }
+
+ // now check whether we've got a main sequence (if
+ // not, we must manually call
+ // EventMultiplexer::notifySlideAnimationsEnd()
+ // above, as e.g. interactive sequences alone
+ // don't block nextEvent() from issuing the next
+ // slide)
+ MainSequenceSearcher aSearcher;
+ if( ::anim::for_each_childNode( mxRootNode, aSearcher ) )
+ mbMainSequenceFound = aSearcher.getMainSequence().is();
+
+ // import successfully done
+ mbHaveAnimations = true;
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE(
+ false,
+ rtl::OUStringToOString(
+ comphelper::anyToString(cppu::getCaughtException()),
+ RTL_TEXTENCODING_UTF8 ) );
+ // TODO(E2): Error handling. For now, bail out
+ }
+
+ mbShowLoaded = true;
+
+ return true;
+}
+
+void SlideImpl::enablePaintOverlay()
+{
+ if( mbUserPaintOverlayEnabled )
+ {
+ mpPaintOverlay = UserPaintOverlay::create( maUserPaintColor,
+ mdUserPaintStrokeWidth,
+ maContext,
+ maPolygons );
+ mbPaintOverlayActive = true;
+ }
+}
+
+void SlideImpl::drawPolygons() const
+{
+ if( mbUserPaintOverlayEnabled )
+ mpPaintOverlay->drawPolygons();
+}
+
+void SlideImpl::addPolygons(PolyPolygonVector aPolygons)
+{
+ if(!aPolygons.empty())
+ {
+ for( PolyPolygonVector::iterator aIter=aPolygons.begin(),
+ aEnd=aPolygons.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ maPolygons.push_back(*aIter);
+ }
+ }
+}
+
+bool SlideImpl::isPaintOverlayActive() const
+{
+ return mbPaintOverlayActive;
+}
+
+void SlideImpl::disablePaintOverlay()
+{
+ if(mbPaintOverlayActive)
+ maPolygons = mpPaintOverlay->getPolygons();
+
+ mpPaintOverlay.reset();
+ mbPaintOverlayActive = false;
+}
+
+::basegfx::B2DRectangle SlideImpl::getSlideRect() const
+{
+ const basegfx::B2ISize slideSize( getSlideSizeImpl() );
+ return ::basegfx::B2DRectangle(0.0,0.0,
+ slideSize.getX(),
+ slideSize.getY());
+}
+
+void SlideImpl::endIntrinsicAnimations()
+{
+ mpSubsettableShapeManager->notifyIntrinsicAnimationsDisabled();
+}
+
+void SlideImpl::startIntrinsicAnimations()
+{
+ mpSubsettableShapeManager->notifyIntrinsicAnimationsEnabled();
+}
+
+bool SlideImpl::applyInitialShapeAttributes(
+ const uno::Reference< animations::XAnimationNode >& xRootAnimationNode )
+{
+ if( !implPrefetchShow() )
+ return false;
+
+ if( !xRootAnimationNode.is() )
+ {
+ meAnimationState = INITIAL_STATE;
+
+ return true; // no animations - no attributes to apply -
+ // succeeded
+ }
+
+ uno::Reference< animations::XTargetPropertiesCreator > xPropsCreator;
+
+ try
+ {
+ ENSURE_OR_RETURN_FALSE( maContext.mxComponentContext.is(),
+ "SlideImpl::applyInitialShapeAttributes(): Invalid component context" );
+
+ uno::Reference<lang::XMultiComponentFactory> xFac(
+ maContext.mxComponentContext->getServiceManager() );
+
+ xPropsCreator.set(
+ xFac->createInstanceWithContext(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.animations.TargetPropertiesCreator") ),
+ maContext.mxComponentContext ),
+ uno::UNO_QUERY_THROW );
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE(
+ false,
+ rtl::OUStringToOString(
+ comphelper::anyToString(cppu::getCaughtException()),
+ RTL_TEXTENCODING_UTF8 ) );
+
+ // could not determine initial shape attributes - this
+ // is an error, as some effects might then be plainly
+ // invisible
+ ENSURE_OR_RETURN_FALSE( false,
+ "SlideImpl::applyInitialShapeAttributes(): "
+ "couldn't create TargetPropertiesCreator." );
+ }
+
+ uno::Sequence< animations::TargetProperties > aProps(
+ xPropsCreator->createInitialTargetProperties( xRootAnimationNode ) );
+
+ // apply extracted values to our shapes
+ const ::std::size_t nSize( aProps.getLength() );
+ for( ::std::size_t i=0; i<nSize; ++i )
+ {
+ sal_Int16 nParaIndex( -1 );
+ uno::Reference< drawing::XShape > xShape( aProps[i].Target,
+ uno::UNO_QUERY );
+
+ if( !xShape.is() )
+ {
+ // not a shape target. Maybe a ParagraphTarget?
+ presentation::ParagraphTarget aParaTarget;
+
+ if( (aProps[i].Target >>= aParaTarget) )
+ {
+ // yep, ParagraphTarget found - extract shape
+ // and index
+ xShape = aParaTarget.Shape;
+ nParaIndex = aParaTarget.Paragraph;
+ }
+ }
+
+ if( xShape.is() )
+ {
+ ShapeSharedPtr pShape( mpLayerManager->lookupShape( xShape ) );
+
+ if( !pShape )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): no shape found for given target" );
+ continue;
+ }
+
+ AttributableShapeSharedPtr pAttrShape(
+ ::boost::dynamic_pointer_cast< AttributableShape >( pShape ) );
+
+ if( !pAttrShape )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): shape found does not "
+ "implement AttributableShape interface" );
+ continue;
+ }
+
+ if( nParaIndex != -1 )
+ {
+ // our target is a paragraph subset, thus look
+ // this up first.
+ const DocTreeNodeSupplier& rNodeSupplier( pAttrShape->getTreeNodeSupplier() );
+
+ pAttrShape = pAttrShape->getSubset(
+ rNodeSupplier.getTreeNode(
+ nParaIndex,
+ DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) );
+
+ if( !pAttrShape )
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): shape found does not "
+ "provide a subset for requested paragraph index" );
+ continue;
+ }
+ }
+
+ const uno::Sequence< beans::NamedValue >& rShapeProps( aProps[i].Properties );
+ const ::std::size_t nShapePropSize( rShapeProps.getLength() );
+ for( ::std::size_t j=0; j<nShapePropSize; ++j )
+ {
+ bool bVisible=false;
+ if( rShapeProps[j].Name.equalsIgnoreAsciiCaseAscii("visibility") &&
+ extractValue( bVisible,
+ rShapeProps[j].Value,
+ pShape,
+ getSlideSize() ))
+ {
+ pAttrShape->setVisibility( bVisible );
+ }
+ else
+ {
+ OSL_ENSURE( false,
+ "SlideImpl::applyInitialShapeAttributes(): Unexpected "
+ "(and unimplemented) property encountered" );
+ }
+ }
+ }
+ }
+
+ meAnimationState = INITIAL_STATE;
+
+ return true;
+}
+
+bool SlideImpl::loadShapes()
+{
+ if( mbShapesLoaded )
+ return true;
+
+ ENSURE_OR_RETURN_FALSE( mxDrawPage.is(),
+ "SlideImpl::loadShapes(): Invalid draw page" );
+ ENSURE_OR_RETURN_FALSE( mpLayerManager,
+ "SlideImpl::loadShapes(): Invalid layer manager" );
+
+ // fetch desired page content
+ // ==========================
+
+ // also take master page content
+ uno::Reference< drawing::XDrawPage > xMasterPage;
+ uno::Reference< drawing::XShapes > xMasterPageShapes;
+ sal_Int32 nCurrCount(0);
+
+ uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mxDrawPage,
+ uno::UNO_QUERY );
+ if( xMasterPageTarget.is() )
+ {
+ xMasterPage = xMasterPageTarget->getMasterPage();
+ xMasterPageShapes.set( xMasterPage,
+ uno::UNO_QUERY );
+
+ if( xMasterPage.is() && xMasterPageShapes.is() )
+ {
+ // TODO(P2): maybe cache master pages here (or treat the
+ // masterpage as a single metafile. At least currently,
+ // masterpages do not contain animation effects)
+ try
+ {
+ // load the masterpage shapes
+ // -------------------------------------------------------------------------
+ ShapeImporter aMPShapesFunctor( xMasterPage,
+ mxDrawPage,
+ mxDrawPagesSupplier,
+ maContext,
+ 0, /* shape num starts at 0 */
+ true );
+
+ mpLayerManager->addShape(
+ aMPShapesFunctor.importBackgroundShape() );
+
+ while( !aMPShapesFunctor.isImportDone() )
+ {
+ ShapeSharedPtr const& rShape(
+ aMPShapesFunctor.importShape() );
+ if( rShape )
+ mpLayerManager->addShape( rShape );
+ }
+ addPolygons(aMPShapesFunctor.getPolygons());
+
+ nCurrCount = xMasterPageShapes->getCount() + 1;
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( ShapeLoadFailedException& )
+ {
+ // TODO(E2): Error handling. For now, bail out
+ OSL_ENSURE( false,
+ "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
+ return false;
+
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+ }
+ }
+
+ try
+ {
+ // load the normal page shapes
+ // -------------------------------------------------------------------------
+
+ ShapeImporter aShapesFunctor( mxDrawPage,
+ mxDrawPage,
+ mxDrawPagesSupplier,
+ maContext,
+ nCurrCount,
+ false );
+
+ while( !aShapesFunctor.isImportDone() )
+ {
+ ShapeSharedPtr const& rShape(
+ aShapesFunctor.importShape() );
+ if( rShape )
+ mpLayerManager->addShape( rShape );
+ }
+ addPolygons(aShapesFunctor.getPolygons());
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( ShapeLoadFailedException& )
+ {
+ // TODO(E2): Error handling. For now, bail out
+ OSL_ENSURE( false,
+ "SlideImpl::loadShapes(): caught ShapeLoadFailedException" );
+ return false;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+
+ mbShapesLoaded = true;
+
+ return true;
+}
+
+basegfx::B2ISize SlideImpl::getSlideSizeImpl() const
+{
+ uno::Reference< beans::XPropertySet > xPropSet(
+ mxDrawPage, uno::UNO_QUERY_THROW );
+
+ sal_Int32 nDocWidth = 0;
+ sal_Int32 nDocHeight = 0;
+ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= nDocWidth;
+ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= nDocHeight;
+
+ return basegfx::B2ISize( nDocWidth, nDocHeight );
+}
+
+} // namespace
+
+
+SlideSharedPtr createSlide( const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const uno::Reference<drawing::XDrawPagesSupplier>& xDrawPages,
+ const uno::Reference< animations::XAnimationNode >& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference< uno::XComponentContext >& xComponentContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ const PolyPolygonVector& rPolyPolygonVector,
+ RGBColor const& rUserPaintColor,
+ double dUserPaintStrokeWidth,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder )
+{
+#ifdef ENABLE_PRESENTER_EXTRA_UI
+ boost::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, xDrawPages, xRootNode, rEventQueue,
+#else
+ (void)xDrawPages;
+ boost::shared_ptr<SlideImpl> pRet( new SlideImpl( xDrawPage, NULL, xRootNode, rEventQueue,
+#endif
+ rEventMultiplexer, rScreenUpdater,
+ rActivitiesQueue, rUserEventQueue,
+ rCursorManager, rViewContainer,
+ xComponentContext, rShapeListenerMap,
+ rShapeCursorMap, rPolyPolygonVector, rUserPaintColor,
+ dUserPaintStrokeWidth, bUserPaintEnabled,
+ bIntrinsicAnimationsAllowed,
+ bDisableAnimationZOrder ));
+
+ rEventMultiplexer.addViewHandler( pRet );
+
+ return pRet;
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/userpaintoverlay.cxx b/slideshow/source/engine/slide/userpaintoverlay.cxx
new file mode 100644
index 000000000000..80a033c79261
--- /dev/null
+++ b/slideshow/source/engine/slide/userpaintoverlay.cxx
@@ -0,0 +1,507 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/presentation/XSlideShowView.hpp>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include "activity.hxx"
+#include "activitiesqueue.hxx"
+#include "slideshowcontext.hxx"
+#include "userpaintoverlay.hxx"
+#include "mouseeventhandler.hxx"
+#include "eventmultiplexer.hxx"
+#include "screenupdater.hxx"
+#include "vieweventhandler.hxx"
+
+#include <boost/bind.hpp>
+#include <boost/noncopyable.hpp>
+#include "slide.hxx"
+#include "cursormanager.hxx"
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class PaintOverlayHandler : public MouseEventHandler,
+ public ViewEventHandler,
+ public UserPaintEventHandler
+ {
+ public:
+ PaintOverlayHandler( const RGBColor& rStrokeColor,
+ double nStrokeWidth,
+ ActivitiesQueue& rActivitiesQueue,
+ ScreenUpdater& rScreenUpdater,
+ const UnoViewContainer& rViews,
+ Slide& rSlide,
+ const PolyPolygonVector& rPolygons ) :
+ mrActivitiesQueue( rActivitiesQueue ),
+ mrScreenUpdater( rScreenUpdater ),
+ maViews(),
+ maPolygons( rPolygons ),
+ maStrokeColor( rStrokeColor ),
+ mnStrokeWidth( nStrokeWidth ),
+ maLastPoint(),
+ maLastMouseDownPos(),
+ mbIsLastPointValid( false ),
+ mbIsLastMouseDownPosValid( false ),
+ //handle the "remove all ink from slide" mode of erasing
+ mbIsEraseAllModeActivated( false ),
+ //handle the "remove stroke by stroke" mode of erasing
+ mbIsEraseModeActivated( false ),
+ mrSlide(rSlide),
+ mnSize(100)
+ {
+ std::for_each( rViews.begin(),
+ rViews.end(),
+ boost::bind( &PaintOverlayHandler::viewAdded,
+ this,
+ _1 ));
+ drawPolygons();
+ }
+
+ virtual void dispose()
+ {
+ maViews.clear();
+ }
+
+ // ViewEventHandler methods
+ virtual void viewAdded( const UnoViewSharedPtr& rView )
+ {
+ maViews.push_back( rView );
+ }
+
+ virtual void viewRemoved( const UnoViewSharedPtr& rView )
+ {
+ maViews.erase( ::std::remove( maViews.begin(),
+ maViews.end(),
+ rView ) );
+ }
+
+ virtual void viewChanged( const UnoViewSharedPtr& /*rView*/ )
+ {
+ // TODO(F2): for persistent drawings, need to store
+ // polygon and repaint here.
+ }
+
+ virtual void viewsChanged()
+ {
+ // TODO(F2): for persistent drawings, need to store
+ // polygon and repaint here.
+ }
+
+ bool colorChanged( RGBColor const& rUserColor )
+ {
+ this->maStrokeColor = rUserColor;
+ this->mbIsEraseModeActivated = false;
+ return true;
+ }
+
+ bool widthChanged( double nUserStrokeWidth )
+ {
+ this->mnStrokeWidth = nUserStrokeWidth;
+ mbIsEraseModeActivated = false;
+ return true;
+ }
+
+ bool eraseAllInkChanged( bool const& rEraseAllInk )
+ {
+ this->mbIsEraseAllModeActivated= rEraseAllInk;
+ // if the erase all mode is activated it will remove all ink from slide,
+ // therefor destroy all the polygons stored
+ if(mbIsEraseAllModeActivated)
+ {
+ // The Erase Mode should be desactivated
+ mbIsEraseModeActivated = false;
+ // must get access to the instance to erase all polygon
+ for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ // fully clear view content to background color
+ (*aIter)->getCanvas()->clear();
+
+ //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
+ SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( (*aIter) ) );
+ ::cppcanvas::CanvasSharedPtr pCanvas( (*aIter)->getCanvas() );
+
+ const ::basegfx::B2DHomMatrix aViewTransform( (*aIter)->getTransformation() );
+ const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
+
+ // setup a canvas with device coordinate space, the slide
+ // bitmap already has the correct dimension.
+ ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
+
+ pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // render at given output position
+ pBitmap->move( aOutPosPixel );
+
+ // clear clip (might have been changed, e.g. from comb
+ // transition)
+ pBitmap->clip( ::basegfx::B2DPolyPolygon() );
+ pBitmap->draw( pDevicePixelCanvas );
+
+ mrScreenUpdater.notifyUpdate(*aIter,true);
+ }
+ maPolygons.clear();
+ }
+ mbIsEraseAllModeActivated=false;
+ return true;
+ }
+
+ bool eraseInkWidthChanged( sal_Int32 rEraseInkSize )
+ {
+ // Change the size
+ this->mnSize=rEraseInkSize;
+ // Changed to mode Erase
+ this->mbIsEraseModeActivated = true;
+ return true;
+ }
+
+ bool switchPenMode()
+ {
+ this->mbIsEraseModeActivated = false;
+ return true;
+ }
+
+ bool switchEraserMode()
+ {
+ this->mbIsEraseModeActivated = true;
+ return true;
+ }
+
+ bool disable()
+ {
+ return true;
+ }
+
+ //Draw all registered polygons.
+ void drawPolygons()
+ {
+ for( PolyPolygonVector::iterator aIter=maPolygons.begin(), aEnd=maPolygons.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ (*aIter)->draw();
+ }
+ // screen update necessary to show painting
+ mrScreenUpdater.notifyUpdate();
+ }
+
+ //Retrieve all registered polygons.
+ PolyPolygonVector getPolygons()
+ {
+ return maPolygons;
+ }
+
+ // MouseEventHandler methods
+ virtual bool handleMousePressed( const awt::MouseEvent& e )
+ {
+ if (e.Buttons == awt::MouseButton::RIGHT)
+ {
+ mbIsLastPointValid = false;
+ return false;
+ }
+
+ if (e.Buttons != awt::MouseButton::LEFT)
+ return false;
+
+ maLastMouseDownPos.setX( e.X );
+ maLastMouseDownPos.setY( e.Y );
+ mbIsLastMouseDownPosValid = true;
+
+ // eat mouse click (though we don't process it
+ // _directly_, it enables the drag mode
+ return true;
+ }
+
+ virtual bool handleMouseReleased( const awt::MouseEvent& e )
+ {
+ if (e.Buttons == awt::MouseButton::RIGHT)
+ {
+ mbIsLastPointValid = false;
+ return false;
+ }
+
+ if (e.Buttons != awt::MouseButton::LEFT)
+ return false;
+
+ // check, whether up- and down press are on exactly
+ // the same pixel. If that's the case, ignore the
+ // click, and pass on the event to low-prio
+ // handlers. This effectively permits effect
+ // advancements via clicks also when user paint is
+ // enabled.
+ if( mbIsLastMouseDownPosValid &&
+ ::basegfx::B2DPoint( e.X,
+ e.Y ) == maLastMouseDownPos )
+ {
+ mbIsLastMouseDownPosValid = false;
+ return false;
+ }
+
+ // invalidate, next downpress will have to start a new
+ // polygon.
+ mbIsLastPointValid = false;
+
+ // eat mouse click (though we don't process it
+ // _directly_, it enables the drag mode
+ return true;
+ }
+
+ virtual bool handleMouseEntered( const awt::MouseEvent& e )
+ {
+ mbIsLastPointValid = true;
+ maLastPoint.setX( e.X );
+ maLastPoint.setY( e.Y );
+
+ return true;
+ }
+
+ virtual bool handleMouseExited( const awt::MouseEvent& )
+ {
+ mbIsLastPointValid = false;
+ mbIsLastMouseDownPosValid = false;
+
+ return true;
+ }
+
+ virtual bool handleMouseDragged( const awt::MouseEvent& e )
+ {
+ if(mbIsEraseModeActivated)
+ {
+ //define the last point as an object
+ //we suppose that there's no way this point could be valid
+ ::basegfx::B2DPolygon aPoly;
+
+ maLastPoint.setX( e.X-mnSize );
+ maLastPoint.setY( e.Y-mnSize );
+
+ aPoly.append( maLastPoint );
+
+ maLastPoint.setX( e.X-mnSize );
+ maLastPoint.setY( e.Y+mnSize );
+
+ aPoly.append( maLastPoint );
+ maLastPoint.setX( e.X+mnSize );
+ maLastPoint.setY( e.Y+mnSize );
+
+ aPoly.append( maLastPoint );
+ maLastPoint.setX( e.X+mnSize );
+ maLastPoint.setY( e.Y-mnSize );
+
+ aPoly.append( maLastPoint );
+ maLastPoint.setX( e.X-mnSize );
+ maLastPoint.setY( e.Y-mnSize );
+
+ aPoly.append( maLastPoint );
+
+ //now we have defined a Polygon that is closed
+
+ //The point is to redraw the LastPoint the way it was originally on the bitmap,
+ //of the slide
+ for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+
+ //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
+ SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( (*aIter) ) );
+ ::cppcanvas::CanvasSharedPtr pCanvas( (*aIter)->getCanvas() );
+
+ ::basegfx::B2DHomMatrix aViewTransform( (*aIter)->getTransformation() );
+ const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
+
+ // setup a canvas with device coordinate space, the slide
+ // bitmap already has the correct dimension.
+ ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
+
+ pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // render at given output position
+ pBitmap->move( aOutPosPixel );
+
+ ::basegfx::B2DPolyPolygon aPolyPoly=::basegfx::B2DPolyPolygon(aPoly);
+ aViewTransform.translate(-aOutPosPixel.getX(), -aOutPosPixel.getY());
+ aPolyPoly.transform(aViewTransform);
+ // set clip so that we just redraw a part of the canvas
+ pBitmap->clip(aPolyPoly);
+ pBitmap->draw( pDevicePixelCanvas );
+
+ mrScreenUpdater.notifyUpdate(*aIter,true);
+ }
+
+ }
+ else
+ {
+ if( !mbIsLastPointValid )
+ {
+ mbIsLastPointValid = true;
+ maLastPoint.setX( e.X );
+ maLastPoint.setY( e.Y );
+ }
+ else
+ {
+ ::basegfx::B2DPolygon aPoly;
+ aPoly.append( maLastPoint );
+
+ maLastPoint.setX( e.X );
+ maLastPoint.setY( e.Y );
+
+ aPoly.append( maLastPoint );
+
+ // paint to all views
+ for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
+ ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( (*aIter)->getCanvas(),
+ aPoly ) );
+
+ if( pPolyPoly )
+ {
+ pPolyPoly->setStrokeWidth(mnStrokeWidth);
+ pPolyPoly->setRGBALineColor( maStrokeColor.getIntegerColor() );
+ pPolyPoly->draw();
+ maPolygons.push_back(pPolyPoly);
+ }
+ }
+
+ // screen update necessary to show painting
+ mrScreenUpdater.notifyUpdate();
+ }
+ }
+ // mouse events captured
+ return true;
+ }
+
+ virtual bool handleMouseMoved( const awt::MouseEvent& /*e*/ )
+ {
+ // not used here
+ return false; // did not handle the event
+ }
+
+
+
+ private:
+ ActivitiesQueue& mrActivitiesQueue;
+ ScreenUpdater& mrScreenUpdater;
+ UnoViewVector maViews;
+ PolyPolygonVector maPolygons;
+ RGBColor maStrokeColor;
+ double mnStrokeWidth;
+ basegfx::B2DPoint maLastPoint;
+ basegfx::B2DPoint maLastMouseDownPos;
+ bool mbIsLastPointValid;
+ bool mbIsLastMouseDownPosValid;
+ // added bool for erasing purpose :
+ bool mbIsEraseAllModeActivated;
+ bool mbIsEraseModeActivated;
+ Slide& mrSlide;
+ sal_Int32 mnSize;
+ };
+
+ UserPaintOverlaySharedPtr UserPaintOverlay::create( const RGBColor& rStrokeColor,
+ double nStrokeWidth,
+ const SlideShowContext& rContext,
+ const PolyPolygonVector& rPolygons )
+ {
+ UserPaintOverlaySharedPtr pRet( new UserPaintOverlay( rStrokeColor,
+ nStrokeWidth,
+ rContext,
+ rPolygons ));
+
+ return pRet;
+ }
+
+ UserPaintOverlay::UserPaintOverlay( const RGBColor& rStrokeColor,
+ double nStrokeWidth,
+ const SlideShowContext& rContext,
+ const PolyPolygonVector& rPolygons ) :
+ mpHandler( new PaintOverlayHandler( rStrokeColor,
+ nStrokeWidth,
+ rContext.mrActivitiesQueue,
+ rContext.mrScreenUpdater,
+ rContext.mrViewContainer,
+ //adding a link to Slide
+ dynamic_cast<Slide&>(rContext.mrCursorManager),
+ rPolygons )),
+ mrMultiplexer( rContext.mrEventMultiplexer )
+ {
+ mrMultiplexer.addClickHandler( mpHandler, 3.0 );
+ mrMultiplexer.addMouseMoveHandler( mpHandler, 3.0 );
+ mrMultiplexer.addViewHandler( mpHandler );
+ mrMultiplexer.addUserPaintHandler(mpHandler);
+ }
+
+ PolyPolygonVector UserPaintOverlay::getPolygons()
+ {
+ return mpHandler->getPolygons();
+ }
+
+ void UserPaintOverlay::drawPolygons()
+ {
+ mpHandler->drawPolygons();
+ }
+
+ UserPaintOverlay::~UserPaintOverlay()
+ {
+ try
+ {
+ mrMultiplexer.removeMouseMoveHandler( mpHandler );
+ mrMultiplexer.removeClickHandler( mpHandler );
+ mrMultiplexer.removeViewHandler( mpHandler );
+ mpHandler->dispose();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slide/userpaintoverlay.hxx b/slideshow/source/engine/slide/userpaintoverlay.hxx
new file mode 100644
index 000000000000..4a9aef115844
--- /dev/null
+++ b/slideshow/source/engine/slide/userpaintoverlay.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_USERPAINTOVERLAY_HXX
+#define INCLUDED_SLIDESHOW_USERPAINTOVERLAY_HXX
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include "unoview.hxx"
+#include "rgbcolor.hxx"
+
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+/* Definition of UserPaintOverlay class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class EventMultiplexer;
+ struct SlideShowContext;
+
+ class PaintOverlayHandler;
+ typedef ::boost::shared_ptr< class UserPaintOverlay > UserPaintOverlaySharedPtr;
+ typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
+ /** Slide overlay, which can be painted into by the user.
+
+ This class registers itself at the EventMultiplexer,
+ listening for mouse clicks and moves. When the mouse is
+ dragged, a hand sketching in the selected color is shown.
+ */
+ class UserPaintOverlay : private boost::noncopyable
+ {
+ public:
+ /** Create a UserPaintOverlay
+
+ @param rStrokeColor
+ Color to use for drawing
+
+ @param nStrokeWidth
+ Width of the stroked path
+ */
+ static UserPaintOverlaySharedPtr create( const RGBColor& rStrokeColor,
+ double nStrokeWidth,
+ const SlideShowContext& rContext,
+ const PolyPolygonVector& rPolygons );
+ ~UserPaintOverlay();
+ PolyPolygonVector getPolygons();
+ void drawPolygons();
+
+ private:
+ UserPaintOverlay( const RGBColor& rStrokeColor,
+ double nStrokeWidth,
+ const SlideShowContext& rContext,
+ const PolyPolygonVector& rPolygons );
+
+ ::boost::shared_ptr<PaintOverlayHandler> mpHandler;
+ EventMultiplexer& mrMultiplexer;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_USERPAINTOVERLAY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slidebitmap.cxx b/slideshow/source/engine/slidebitmap.cxx
new file mode 100644
index 000000000000..4afa0ff07059
--- /dev/null
+++ b/slideshow/source/engine/slidebitmap.cxx
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <slidebitmap.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <canvas/canvastools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ SlideBitmap::SlideBitmap( const ::cppcanvas::BitmapSharedPtr& rBitmap ) :
+ maOutputPos(),
+ maClipPoly(),
+ mxBitmap()
+ {
+ if( rBitmap )
+ mxBitmap = rBitmap->getUNOBitmap();
+
+ ENSURE_OR_THROW( mxBitmap.is(), "SlideBitmap::SlideBitmap(): Invalid bitmap" );
+ }
+
+ bool SlideBitmap::draw( const ::cppcanvas::CanvasSharedPtr& rCanvas ) const
+ {
+ ENSURE_OR_RETURN_FALSE( rCanvas && rCanvas->getUNOCanvas().is(),
+ "SlideBitmap::draw(): Invalid canvas" );
+
+ // selectively only copy the transformation from current viewstate,
+ // don't want no clipping here.
+ rendering::ViewState aViewState;
+ aViewState.AffineTransform = rCanvas->getViewState().AffineTransform;
+
+ rendering::RenderState aRenderState;
+ ::canvas::tools::initRenderState( aRenderState );
+
+ const basegfx::B2DHomMatrix aTranslation(basegfx::tools::createTranslateB2DHomMatrix(maOutputPos));
+ ::canvas::tools::setRenderStateTransform( aRenderState, aTranslation );
+
+ try
+ {
+ if( maClipPoly.count() )
+ {
+ // TODO(P1): Buffer the clip polygon
+ aRenderState.Clip =
+ ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
+ rCanvas->getUNOCanvas()->getDevice(),
+ maClipPoly );
+ }
+
+ rCanvas->getUNOCanvas()->drawBitmap( mxBitmap,
+ aViewState,
+ aRenderState );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ ::basegfx::B2ISize SlideBitmap::getSize() const
+ {
+ return ::basegfx::unotools::b2ISizeFromIntegerSize2D( mxBitmap->getSize() );
+ }
+
+ void SlideBitmap::move( const ::basegfx::B2DPoint& rNewPos )
+ {
+ maOutputPos = rNewPos;
+ }
+
+ void SlideBitmap::clip( const ::basegfx::B2DPolyPolygon& rClipPoly )
+ {
+ maClipPoly = rClipPoly;
+ }
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > SlideBitmap::getXBitmap()
+ {
+ return mxBitmap;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slideshowcontext.cxx b/slideshow/source/engine/slideshowcontext.cxx
new file mode 100644
index 000000000000..cbca36848751
--- /dev/null
+++ b/slideshow/source/engine/slideshowcontext.cxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_slideshow.hxx"
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include "slideshowcontext.hxx"
+#include "subsettableshapemanager.hxx"
+#include "screenupdater.hxx"
+#include "eventqueue.hxx"
+#include "activitiesqueue.hxx"
+#include "usereventqueue.hxx"
+#include "eventmultiplexer.hxx"
+#include "unoviewcontainer.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+namespace internal
+{
+
+SlideShowContext::SlideShowContext( SubsettableShapeManagerSharedPtr& rSubsettableShapeManager,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const uno::Reference<
+ uno::XComponentContext>& rComponentContext ) :
+ mpSubsettableShapeManager( rSubsettableShapeManager ),
+ mrEventQueue( rEventQueue ),
+ mrEventMultiplexer( rEventMultiplexer ),
+ mrScreenUpdater( rScreenUpdater ),
+ mrActivitiesQueue( rActivitiesQueue ),
+ mrUserEventQueue( rUserEventQueue ),
+ mrCursorManager( rCursorManager ),
+ mrViewContainer( rViewContainer ),
+ mxComponentContext( rComponentContext )
+ {}
+
+void SlideShowContext::dispose()
+{
+ mxComponentContext.clear();
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slideshowimpl.cxx b/slideshow/source/engine/slideshowimpl.cxx
new file mode 100644
index 000000000000..41b5f664a341
--- /dev/null
+++ b/slideshow/source/engine/slideshowimpl.cxx
@@ -0,0 +1,2538 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase1.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/compbase2.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <comphelper/make_shared_from_uno.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/optional.hxx>
+#include <comphelper/servicedecl.hxx>
+#include <comphelper/namecontainer.hxx>
+
+#include <cppcanvas/spritecanvas.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include <tools/debug.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+
+#include <vcl/font.hxx>
+#include "rtl/ref.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/awt/XPaintListener.hpp>
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/animations/TransitionType.hpp>
+#include <com/sun/star/animations/TransitionSubType.hpp>
+#include <com/sun/star/presentation/XSlideShow.hpp>
+#include <com/sun/star/presentation/XSlideShowListener.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/XLayer.hpp>
+#include <com/sun/star/drawing/XLayerSupplier.hpp>
+#include <com/sun/star/drawing/XLayerManager.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+#include "com/sun/star/uno/Reference.hxx"
+#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
+
+#include "unoviewcontainer.hxx"
+#include "transitionfactory.hxx"
+#include "eventmultiplexer.hxx"
+#include "usereventqueue.hxx"
+#include "eventqueue.hxx"
+#include "cursormanager.hxx"
+#include "slideshowcontext.hxx"
+#include "activitiesqueue.hxx"
+#include "activitiesfactory.hxx"
+#include "interruptabledelayevent.hxx"
+#include "slide.hxx"
+#include "shapemaps.hxx"
+#include "slideview.hxx"
+#include "tools.hxx"
+#include "unoview.hxx"
+#include "slidebitmap.hxx"
+#include "rehearsetimingsactivity.hxx"
+#include "waitsymbol.hxx"
+#include "effectrewinder.hxx"
+#include "framerate.hxx"
+
+#include <boost/noncopyable.hpp>
+#include <boost/bind.hpp>
+
+#include <map>
+#include <vector>
+#include <iterator>
+#include <string>
+#include <algorithm>
+#include <stdio.h>
+#include <iostream>
+
+using namespace com::sun::star;
+using namespace ::slideshow::internal;
+
+namespace {
+
+/** During animations the update() method tells its caller to call it as
+ soon as possible. This gives us more time to render the next frame and
+ still maintain a steady frame rate. This class is responsible for
+ synchronizing the display of new frames and thus keeping the frame rate
+ steady.
+*/
+class FrameSynchronization
+{
+public:
+ /** Create new object with a predefined duration between two frames.
+ @param nFrameDuration
+ The preferred duration between the display of two frames in
+ seconds.
+ */
+ FrameSynchronization (const double nFrameDuration);
+
+ /** Set the current time as the time at which the current frame is
+ displayed. From this the target time of the next frame is derived.
+ */
+ void MarkCurrentFrame (void);
+
+ /** When there is time left until the next frame is due then wait.
+ Otherwise return without delay.
+ */
+ void Synchronize (void);
+
+ /** Activate frame synchronization when an animation is active and
+ frames are to be displayed in a steady rate. While active
+ Synchronize() will wait until the frame duration time has passed.
+ */
+ void Activate (void);
+
+ /** Deactivate frame sychronization when no animation is active and the
+ time between frames depends on user actions and other external
+ sources. While deactivated Synchronize() will return without delay.
+ */
+ void Deactivate (void);
+
+ /** Return the current time of the timer. It is not synchronized with
+ any other timer so its absolute values are of no concern. Typically
+ used during debugging to measure durations.
+ */
+ double GetCurrentTime (void) const;
+
+private:
+ /** The timer that is used for synchronization is independent from the
+ one used by SlideShowImpl: it is not paused or modified by
+ animations.
+ */
+ canvas::tools::ElapsedTime maTimer;
+ /** Time between the display of frames. Enforced only when mbIsActive
+ is <TRUE/>.
+ */
+ const double mnFrameDuration;
+ /** Time (of maTimer) when the next frame shall be displayed.
+ Synchronize() will wait until this time.
+ */
+ double mnNextFrameTargetTime;
+ /** Synchronize() will wait only when this flag is <TRUE/>. Otherwise
+ it returns immediately.
+ */
+ bool mbIsActive;
+};
+
+
+
+
+/******************************************************************************
+
+ SlideShowImpl
+
+ This class encapsulates the slideshow presentation viewer.
+
+ With an instance of this class, it is possible to statically
+ and dynamically show a presentation, as defined by the
+ constructor-provided draw model (represented by a sequence
+ of ::com::sun::star::drawing::XDrawPage objects).
+
+ It is possible to show the presentation on multiple views
+ simultaneously (e.g. for a multi-monitor setup). Since this
+ class also relies on user interaction, the corresponding
+ XSlideShowView interface provides means to register some UI
+ event listeners (mostly borrowed from awt::XWindow interface).
+
+ Since currently (mid 2004), OOo isn't very well suited to
+ multi-threaded rendering, this class relies on <em>very
+ frequent</em> external update() calls, which will render the
+ next frame of animations. This works as follows: after the
+ displaySlide() has been successfully called (which setup and
+ starts an actual slide show), the update() method must be
+ called until it returns false.
+ Effectively, this puts the burden of providing
+ concurrency to the clients of this class, which, as noted
+ above, is currently unavoidable with the current state of
+ affairs (I've actually tried threading here, but failed
+ miserably when using the VCL canvas as the render backend -
+ deadlocked).
+
+ ******************************************************************************/
+
+typedef cppu::WeakComponentImplHelper1<presentation::XSlideShow> SlideShowImplBase;
+
+typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
+
+/// Maps XDrawPage for annotations persistence
+typedef ::std::map< ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage>,
+ PolyPolygonVector> PolygonMap;
+
+class SlideShowImpl : private cppu::BaseMutex,
+ public CursorManager,
+ public SlideShowImplBase
+{
+public:
+ explicit SlideShowImpl(
+ uno::Reference<uno::XComponentContext> const& xContext );
+
+ /** Notify that the transition phase of the current slide
+ has ended.
+
+ The life of a slide has three phases: the transition
+ phase, when the previous slide vanishes, and the
+ current slide becomes visible, the shape animation
+ phase, when shape effects are running, and the phase
+ after the last shape animation has ended, but before
+ the next slide transition starts.
+
+ This method notifies the end of the first phase.
+
+ @param bPaintSlide
+ When true, Slide::show() is passed a true as well, denoting
+ explicit paint of slide content. Pass false here, if e.g. a
+ slide transition has already rendered the initial slide image.
+ */
+ void notifySlideTransitionEnded( bool bPaintSlide );
+
+ /** Notify that the shape animation phase of the current slide
+ has ended.
+
+ The life of a slide has three phases: the transition
+ phase, when the previous slide vanishes, and the
+ current slide becomes visible, the shape animation
+ phase, when shape effects are running, and the phase
+ after the last shape animation has ended, but before
+ the next slide transition starts.
+
+ This method notifies the end of the second phase.
+ */
+ void notifySlideAnimationsEnded();
+
+ /** Notify that the slide has ended.
+
+ The life of a slide has three phases: the transition
+ phase, when the previous slide vanishes, and the
+ current slide becomes visible, the shape animation
+ phase, when shape effects are running, and the phase
+ after the last shape animation has ended, but before
+ the next slide transition starts.
+
+ This method notifies the end of the third phase.
+ */
+ void notifySlideEnded (const bool bReverse);
+
+ /** Notification from eventmultiplexer that a hyperlink
+ has been clicked.
+ */
+ bool notifyHyperLinkClicked( rtl::OUString const& hyperLink );
+
+ /** Notification from eventmultiplexer that an animation event has occoured.
+ This will be forewarded to all registered XSlideShowListener
+ */
+ bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );
+
+private:
+ // XSlideShow:
+ virtual sal_Bool SAL_CALL nextEffect() throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL previousEffect() throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL startShapeActivity(
+ uno::Reference<drawing::XShape> const& xShape )
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL stopShapeActivity(
+ uno::Reference<drawing::XShape> const& xShape )
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL pause( sal_Bool bPauseShow )
+ throw (uno::RuntimeException);
+ virtual uno::Reference<drawing::XDrawPage> SAL_CALL getCurrentSlide()
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL displaySlide(
+ uno::Reference<drawing::XDrawPage> const& xSlide,
+ uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
+ uno::Reference<animations::XAnimationNode> const& xRootNode,
+ uno::Sequence<beans::PropertyValue> const& rProperties )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL registerUserPaintPolygons( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xDocFactory ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL setProperty(
+ beans::PropertyValue const& rProperty ) throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL addView(
+ uno::Reference<presentation::XSlideShowView> const& xView )
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL removeView(
+ uno::Reference<presentation::XSlideShowView> const& xView )
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL update( double & nNextTimeout )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL addSlideShowListener(
+ uno::Reference<presentation::XSlideShowListener> const& xListener )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL removeSlideShowListener(
+ uno::Reference<presentation::XSlideShowListener> const& xListener )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL addShapeEventListener(
+ uno::Reference<presentation::XShapeEventListener> const& xListener,
+ uno::Reference<drawing::XShape> const& xShape )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL removeShapeEventListener(
+ uno::Reference<presentation::XShapeEventListener> const& xListener,
+ uno::Reference<drawing::XShape> const& xShape )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL setShapeCursor(
+ uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
+ throw (uno::RuntimeException);
+
+
+ // CursorManager
+ // -----------------------------------------------------------
+
+ virtual bool requestCursor( sal_Int16 nCursorShape );
+ virtual void resetCursor();
+
+ /** This is somewhat similar to displaySlide when called for the current
+ slide. It has been simplified to take advantage of that no slide
+ change takes place. Furthermore it does not show the slide
+ transition.
+ */
+ void redisplayCurrentSlide (void);
+
+protected:
+ // WeakComponentImplHelperBase
+ virtual void SAL_CALL disposing();
+
+ bool isDisposed() const
+ {
+ return (rBHelper.bDisposed || rBHelper.bInDispose);
+ }
+
+private:
+ struct SeparateListenerImpl; friend struct SeparateListenerImpl;
+ struct PrefetchPropertiesFunc; friend struct PrefetchPropertiesFunc;
+
+ /// Stop currently running show.
+ void stopShow();
+
+ ///Find a polygons vector in maPolygons (map)
+ PolygonMap::iterator findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage);
+
+ /// Creates a new slide.
+ SlideSharedPtr makeSlide(
+ uno::Reference<drawing::XDrawPage> const& xDrawPage,
+ uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
+ uno::Reference<animations::XAnimationNode> const& xRootNode );
+
+ /// Checks whether the given slide/animation node matches mpPrefetchSlide
+ static bool matches(
+ SlideSharedPtr const& pSlide,
+ uno::Reference<drawing::XDrawPage> const& xSlide,
+ uno::Reference<animations::XAnimationNode> const& xNode )
+ {
+ if (pSlide)
+ return (pSlide->getXDrawPage() == xSlide &&
+ pSlide->getXAnimationNode() == xNode);
+ else
+ return (!xSlide.is() && !xNode.is());
+ }
+
+ /// Resets the current slide transition sound object with a new one:
+ SoundPlayerSharedPtr resetSlideTransitionSound(
+ uno::Any const& url = uno::Any(), bool bLoopSound = false );
+
+ /// stops the current slide transition sound
+ void stopSlideTransitionSound();
+
+ /** Prepare a slide transition
+
+ This method registers all necessary events and
+ activities for a slide transition.
+
+ @return the slide change activity, or NULL for no transition effect
+ */
+ ActivitySharedPtr createSlideTransition(
+ const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const SlideSharedPtr& rLeavingSlide,
+ const SlideSharedPtr& rEnteringSlide,
+ const EventSharedPtr& rTransitionEndEvent );
+
+ /** Request/release the wait symbol. The wait symbol is displayed when
+ there are more requests then releases. Locking the wait symbol
+ helps to avoid intermediate repaints.
+
+ Do not call this method directly. Use WaitSymbolLock instead.
+ */
+ void requestWaitSymbol (void);
+ void releaseWaitSymbol (void);
+
+ class WaitSymbolLock {public:
+ WaitSymbolLock(SlideShowImpl& rSlideShowImpl) : mrSlideShowImpl(rSlideShowImpl)
+ { mrSlideShowImpl.requestWaitSymbol(); }
+ ~WaitSymbolLock(void)
+ { mrSlideShowImpl.releaseWaitSymbol(); }
+ private: SlideShowImpl& mrSlideShowImpl;
+ };
+
+
+ /// Filter requested cursor shape against hard slideshow cursors (wait, etc.)
+ sal_Int16 calcActiveCursor( sal_Int16 nCursorShape ) const;
+
+ /** This method is called asynchronously to finish the rewinding of an
+ effect to the previous slide that was initiated earlier.
+ */
+ void rewindEffectToPreviousSlide (void);
+
+ /// all registered views
+ UnoViewContainer maViewContainer;
+
+ /// all registered slide show listeners
+ cppu::OInterfaceContainerHelper maListenerContainer;
+
+ /// map of vectors, containing all registered listeners for a shape
+ ShapeEventListenerMap maShapeEventListeners;
+ /// map of sal_Int16 values, specifying the mouse cursor for every shape
+ ShapeCursorMap maShapeCursors;
+
+ //map of vector of Polygons, containing polygons drawn on each slide.
+ PolygonMap maPolygons;
+
+ boost::optional<RGBColor> maUserPaintColor;
+
+ boost::optional<double> maUserPaintStrokeWidth;
+
+ //changed for the eraser project
+ boost::optional<bool> maEraseAllInk;
+ boost::optional<bool> maSwitchPenMode;
+ boost::optional<bool> maSwitchEraserMode;
+ boost::optional<sal_Int32> maEraseInk;
+ //end changed
+
+ boost::shared_ptr<canvas::tools::ElapsedTime> mpPresTimer;
+ ScreenUpdater maScreenUpdater;
+ EventQueue maEventQueue;
+ EventMultiplexer maEventMultiplexer;
+ ActivitiesQueue maActivitiesQueue;
+ UserEventQueue maUserEventQueue;
+ SubsettableShapeManagerSharedPtr mpDummyPtr;
+
+ boost::shared_ptr<SeparateListenerImpl> mpListener;
+
+ boost::shared_ptr<RehearseTimingsActivity> mpRehearseTimingsActivity;
+ boost::shared_ptr<WaitSymbol> mpWaitSymbol;
+
+ /// the current slide transition sound object:
+ SoundPlayerSharedPtr mpCurrentSlideTransitionSound;
+
+ uno::Reference<uno::XComponentContext> mxComponentContext;
+ uno::Reference<
+ presentation::XTransitionFactory> mxOptionalTransitionFactory;
+
+ /// the previously running slide
+ SlideSharedPtr mpPreviousSlide;
+ /// the currently running slide
+ SlideSharedPtr mpCurrentSlide;
+ /// the already prefetched slide: best candidate for upcoming slide
+ SlideSharedPtr mpPrefetchSlide;
+ /// slide to be prefetched: best candidate for upcoming slide
+ uno::Reference<drawing::XDrawPage> mxPrefetchSlide;
+ /// save the XDrawPagesSupplier to retieve polygons
+ uno::Reference<drawing::XDrawPagesSupplier> mxDrawPagesSupplier;
+ /// slide animation to be prefetched:
+ uno::Reference<animations::XAnimationNode> mxPrefetchAnimationNode;
+
+ sal_Int16 mnCurrentCursor;
+
+ sal_Int32 mnWaitSymbolRequestCount;
+ bool mbAutomaticAdvancementMode;
+ bool mbImageAnimationsAllowed;
+ bool mbNoSlideTransitions;
+ bool mbMouseVisible;
+ bool mbForceManualAdvance;
+ bool mbShowPaused;
+ bool mbSlideShowIdle;
+ bool mbDisableAnimationZOrder;
+
+ EffectRewinder maEffectRewinder;
+ FrameSynchronization maFrameSynchronization;
+};
+
+
+/** Separate event listener for animation, view and hyperlink events.
+
+ This handler is registered for slide animation end, view and
+ hyperlink events at the global EventMultiplexer, and forwards
+ notifications to the SlideShowImpl
+*/
+struct SlideShowImpl::SeparateListenerImpl : public EventHandler,
+ public ViewRepaintHandler,
+ public HyperlinkHandler,
+ public AnimationEventHandler,
+ private boost::noncopyable
+{
+ SlideShowImpl& mrShow;
+ ScreenUpdater& mrScreenUpdater;
+ EventQueue& mrEventQueue;
+
+ SeparateListenerImpl( SlideShowImpl& rShow,
+ ScreenUpdater& rScreenUpdater,
+ EventQueue& rEventQueue ) :
+ mrShow( rShow ),
+ mrScreenUpdater( rScreenUpdater ),
+ mrEventQueue( rEventQueue )
+ {}
+
+ // EventHandler
+ virtual bool handleEvent()
+ {
+ // DON't call notifySlideAnimationsEnded()
+ // directly, but queue an event. handleEvent()
+ // might be called from e.g.
+ // showNext(), and notifySlideAnimationsEnded() must not be called
+ // in recursion. Note that the event is scheduled for the next
+ // frame so that its expensive execution does not come in between
+ // sprite hiding and shape redraw (at the end of the animation of a
+ // shape), which would cause a flicker.
+ mrEventQueue.addEventForNextRound(
+ makeEvent(
+ boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, boost::ref(mrShow) ),
+ "SlideShowImpl::notifySlideAnimationsEnded"));
+ return true;
+ }
+
+ // ViewRepaintHandler
+ virtual void viewClobbered( const UnoViewSharedPtr& rView )
+ {
+ // given view needs repaint, request update
+ mrScreenUpdater.notifyUpdate(rView, true);
+ }
+
+ // HyperlinkHandler
+ virtual bool handleHyperlink( ::rtl::OUString const& rLink )
+ {
+ return mrShow.notifyHyperLinkClicked(rLink);
+ }
+
+ // AnimationEventHandler
+ virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
+ {
+ return mrShow.handleAnimationEvent(rNode);
+ }
+};
+
+
+SlideShowImpl::SlideShowImpl(
+ uno::Reference<uno::XComponentContext> const& xContext )
+ : SlideShowImplBase(m_aMutex),
+ maViewContainer(),
+ maListenerContainer( m_aMutex ),
+ maShapeEventListeners(),
+ maShapeCursors(),
+ maUserPaintColor(),
+ maUserPaintStrokeWidth(4.0),
+ mpPresTimer( new canvas::tools::ElapsedTime ),
+ maScreenUpdater(maViewContainer),
+ maEventQueue( mpPresTimer ),
+ maEventMultiplexer( maEventQueue,
+ maViewContainer ),
+ maActivitiesQueue( mpPresTimer ),
+ maUserEventQueue( maEventMultiplexer,
+ maEventQueue,
+ *this ),
+ mpDummyPtr(),
+ mpListener(),
+ mpRehearseTimingsActivity(),
+ mpWaitSymbol(),
+ mpCurrentSlideTransitionSound(),
+ mxComponentContext( xContext ),
+ mxOptionalTransitionFactory(),
+ mpCurrentSlide(),
+ mpPrefetchSlide(),
+ mxPrefetchSlide(),
+ mxDrawPagesSupplier(),
+ mxPrefetchAnimationNode(),
+ mnCurrentCursor(awt::SystemPointer::ARROW),
+ mnWaitSymbolRequestCount(0),
+ mbAutomaticAdvancementMode(false),
+ mbImageAnimationsAllowed( true ),
+ mbNoSlideTransitions( false ),
+ mbMouseVisible( true ),
+ mbForceManualAdvance( false ),
+ mbShowPaused( false ),
+ mbSlideShowIdle( true ),
+ mbDisableAnimationZOrder( false ),
+ maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue),
+ maFrameSynchronization(1.0 / FrameRate::PreferredFramesPerSecond)
+
+{
+ // keep care not constructing any UNO references to this inside ctor,
+ // shift that code to create()!
+
+ uno::Reference<lang::XMultiComponentFactory> xFactory(
+ mxComponentContext->getServiceManager() );
+
+ if( xFactory.is() )
+ {
+ try
+ {
+ // #i82460# try to retrieve special transition factory
+ mxOptionalTransitionFactory.set(
+ xFactory->createInstanceWithContext(
+ ::rtl::OUString::createFromAscii( "com.sun.star.presentation.TransitionFactory" ),
+ mxComponentContext ),
+ uno::UNO_QUERY );
+ }
+ catch (loader::CannotActivateFactoryException const&)
+ {
+ }
+ }
+
+ mpListener.reset( new SeparateListenerImpl(
+ *this,
+ maScreenUpdater,
+ maEventQueue ));
+ maEventMultiplexer.addSlideAnimationsEndHandler( mpListener );
+ maEventMultiplexer.addViewRepaintHandler( mpListener );
+ maEventMultiplexer.addHyperlinkHandler( mpListener, 0.0 );
+ maEventMultiplexer.addAnimationStartHandler( mpListener );
+ maEventMultiplexer.addAnimationEndHandler( mpListener );
+}
+
+// we are about to be disposed (someone call dispose() on us)
+void SlideShowImpl::disposing()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ maEffectRewinder.dispose();
+
+ // stop slide transition sound, if any:
+ stopSlideTransitionSound();
+
+ mxComponentContext.clear();
+
+ if( mpCurrentSlideTransitionSound )
+ {
+ mpCurrentSlideTransitionSound->dispose();
+ mpCurrentSlideTransitionSound.reset();
+ }
+
+ mpWaitSymbol.reset();
+
+ if( mpRehearseTimingsActivity )
+ {
+ mpRehearseTimingsActivity->dispose();
+ mpRehearseTimingsActivity.reset();
+ }
+
+ if( mpListener )
+ {
+ maEventMultiplexer.removeSlideAnimationsEndHandler(mpListener);
+ maEventMultiplexer.removeViewRepaintHandler(mpListener);
+ maEventMultiplexer.removeHyperlinkHandler(mpListener);
+ maEventMultiplexer.removeAnimationStartHandler( mpListener );
+ maEventMultiplexer.removeAnimationEndHandler( mpListener );
+
+ mpListener.reset();
+ }
+
+ maUserEventQueue.clear();
+ maActivitiesQueue.clear();
+ maEventMultiplexer.clear();
+ maEventQueue.clear();
+ mpPresTimer.reset();
+ maShapeCursors.clear();
+ maShapeEventListeners.clear();
+
+ // send all listeners a disposing() that we are going down:
+ maListenerContainer.disposeAndClear(
+ lang::EventObject( static_cast<cppu::OWeakObject *>(this) ) );
+
+ maViewContainer.dispose();
+
+ // release slides:
+ mxPrefetchAnimationNode.clear();
+ mxPrefetchSlide.clear();
+ mpPrefetchSlide.reset();
+ mpCurrentSlide.reset();
+ mpPreviousSlide.reset();
+}
+
+/// stops the current slide transition sound
+void SlideShowImpl::stopSlideTransitionSound()
+{
+ if (mpCurrentSlideTransitionSound)
+ {
+ mpCurrentSlideTransitionSound->stopPlayback();
+ mpCurrentSlideTransitionSound->dispose();
+ mpCurrentSlideTransitionSound.reset();
+ }
+ }
+
+SoundPlayerSharedPtr SlideShowImpl::resetSlideTransitionSound( const uno::Any& rSound, bool bLoopSound )
+{
+ sal_Bool bStopSound = sal_False;
+ rtl::OUString url;
+
+ if( !(rSound >>= bStopSound) )
+ bStopSound = sal_False;
+ rSound >>= url;
+
+ if( !bStopSound && (url.getLength() == 0) )
+ return SoundPlayerSharedPtr();
+
+ stopSlideTransitionSound();
+
+ if (url.getLength() > 0)
+ {
+ try
+ {
+ mpCurrentSlideTransitionSound = SoundPlayer::create(
+ maEventMultiplexer, url, mxComponentContext );
+ mpCurrentSlideTransitionSound->setPlaybackLoop( bLoopSound );
+ }
+ catch (lang::NoSupportException const&)
+ {
+ // catch possible exceptions from SoundPlayer, since
+ // being not able to playback the sound is not a hard
+ // error here (still, the slide transition should be
+ // shown).
+ }
+ }
+ return mpCurrentSlideTransitionSound;
+}
+
+ActivitySharedPtr SlideShowImpl::createSlideTransition(
+ const uno::Reference< drawing::XDrawPage >& xDrawPage,
+ const SlideSharedPtr& rLeavingSlide,
+ const SlideSharedPtr& rEnteringSlide,
+ const EventSharedPtr& rTransitionEndEvent)
+{
+ ENSURE_OR_THROW( !maViewContainer.empty(),
+ "createSlideTransition(): No views" );
+ ENSURE_OR_THROW( rEnteringSlide,
+ "createSlideTransition(): No entering slide" );
+
+ // return empty transition, if slide transitions
+ // are disabled.
+ if (mbNoSlideTransitions)
+ return ActivitySharedPtr();
+
+ // retrieve slide change parameters from XDrawPage
+ uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
+ uno::UNO_QUERY );
+
+ if( !xPropSet.is() )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "Slide has no PropertySet - assuming no transition\n" );
+ return ActivitySharedPtr();
+ }
+
+ sal_Int16 nTransitionType(0);
+ if( !getPropertyValue( nTransitionType,
+ xPropSet,
+ OUSTR("TransitionType" )) )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "Could not extract slide transition type from XDrawPage - assuming no transition\n" );
+ return ActivitySharedPtr();
+ }
+
+ sal_Int16 nTransitionSubType(0);
+ if( !getPropertyValue( nTransitionSubType,
+ xPropSet,
+ OUSTR("TransitionSubtype" )) )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "Could not extract slide transition subtype from XDrawPage - assuming no transition\n" );
+ return ActivitySharedPtr();
+ }
+
+ bool bTransitionDirection(false);
+ if( !getPropertyValue( bTransitionDirection,
+ xPropSet,
+ OUSTR("TransitionDirection")) )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "Could not extract slide transition direction from XDrawPage - assuming default direction\n" );
+ }
+
+ sal_Int32 aUnoColor(0);
+ if( !getPropertyValue( aUnoColor,
+ xPropSet,
+ OUSTR("TransitionFadeColor")) )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "Could not extract slide transition fade color from XDrawPage - assuming black\n" );
+ }
+
+ const RGBColor aTransitionFadeColor( unoColor2RGBColor( aUnoColor ));
+
+ uno::Any aSound;
+ sal_Bool bLoopSound = sal_False;
+
+ if( !getPropertyValue( aSound, xPropSet, OUSTR("Sound")) )
+ OSL_TRACE( "createSlideTransition(): Could not determine transition sound effect URL from XDrawPage - using no sound\n" );
+
+ if( !getPropertyValue( bLoopSound, xPropSet, OUSTR("LoopSound") ) )
+ OSL_TRACE( "createSlideTransition(): Could not get slide property 'LoopSound' - using no sound\n" );
+
+ NumberAnimationSharedPtr pTransition(
+ TransitionFactory::createSlideTransition(
+ rLeavingSlide,
+ rEnteringSlide,
+ maViewContainer,
+ maScreenUpdater,
+ maEventMultiplexer,
+ mxOptionalTransitionFactory,
+ nTransitionType,
+ nTransitionSubType,
+ bTransitionDirection,
+ aTransitionFadeColor,
+ resetSlideTransitionSound( aSound, bLoopSound ) ));
+
+ if( !pTransition )
+ return ActivitySharedPtr(); // no transition effect has been
+ // generated. Normally, that means
+ // that simply no transition is
+ // set on this slide.
+
+ double nTransitionDuration(0.0);
+ if( !getPropertyValue( nTransitionDuration,
+ xPropSet,
+ OUSTR("TransitionDuration")) )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "Could not extract slide transition duration from XDrawPage - assuming no transition\n" );
+ return ActivitySharedPtr();
+ }
+
+ sal_Int32 nMinFrames(5);
+ if( !getPropertyValue( nMinFrames,
+ xPropSet,
+ OUSTR("MinimalFrameNumber")) )
+ {
+ OSL_TRACE( "createSlideTransition(): "
+ "No minimal number of frames given - assuming 5\n" );
+ }
+
+ // prefetch slide transition bitmaps, but postpone it after
+ // displaySlide() has finished - sometimes, view size has not yet
+ // reached final size
+ maEventQueue.addEvent(
+ makeEvent(
+ boost::bind(
+ &::slideshow::internal::Animation::prefetch,
+ pTransition,
+ AnimatableShapeSharedPtr(),
+ ShapeAttributeLayerSharedPtr()),
+ "Animation::prefetch"));
+
+ return ActivitySharedPtr(
+ ActivitiesFactory::createSimpleActivity(
+ ActivitiesFactory::CommonParameters(
+ rTransitionEndEvent,
+ maEventQueue,
+ maActivitiesQueue,
+ nTransitionDuration,
+ nMinFrames,
+ false,
+ boost::optional<double>(1.0),
+ 0.0,
+ 0.0,
+ ShapeSharedPtr(),
+ rEnteringSlide->getSlideSize() ),
+ pTransition,
+ true ));
+}
+
+PolygonMap::iterator SlideShowImpl::findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage)
+{
+ // TODO(P2) : Optimze research in the map.
+ bool bFound = false;
+ PolygonMap::iterator aIter=maPolygons.begin();
+
+
+ while(aIter!=maPolygons.end() && !bFound)
+ {
+ if(aIter->first == xDrawPage)
+ bFound = true;
+ else
+ aIter++;
+ }
+
+ return aIter;
+}
+
+SlideSharedPtr SlideShowImpl::makeSlide(
+ uno::Reference<drawing::XDrawPage> const& xDrawPage,
+ uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
+ uno::Reference<animations::XAnimationNode> const& xRootNode )
+{
+ if( !xDrawPage.is() )
+ return SlideSharedPtr();
+
+ //Retrieve polygons for the current slide
+ PolygonMap::iterator aIter;
+ aIter = findPolygons(xDrawPage);
+
+ const SlideSharedPtr pSlide( createSlide(xDrawPage,
+ xDrawPages,
+ xRootNode,
+ maEventQueue,
+ maEventMultiplexer,
+ maScreenUpdater,
+ maActivitiesQueue,
+ maUserEventQueue,
+ *this,
+ maViewContainer,
+ mxComponentContext,
+ maShapeEventListeners,
+ maShapeCursors,
+ (aIter != maPolygons.end()) ? aIter->second : PolyPolygonVector(),
+ maUserPaintColor ? *maUserPaintColor : RGBColor(),
+ *maUserPaintStrokeWidth,
+ !!maUserPaintColor,
+ mbImageAnimationsAllowed,
+ mbDisableAnimationZOrder) );
+
+ // prefetch show content (reducing latency for slide
+ // bitmap and effect start later on)
+ pSlide->prefetch();
+
+ return pSlide;
+}
+
+void SlideShowImpl::requestWaitSymbol (void)
+{
+ ++mnWaitSymbolRequestCount;
+ OSL_ASSERT(mnWaitSymbolRequestCount>0);
+
+ if (mnWaitSymbolRequestCount == 1)
+ {
+ if( !mpWaitSymbol )
+ {
+ // fall back to cursor
+ requestCursor(calcActiveCursor(mnCurrentCursor));
+ }
+ else
+ mpWaitSymbol->show();
+ }
+}
+
+void SlideShowImpl::releaseWaitSymbol (void)
+{
+ --mnWaitSymbolRequestCount;
+ OSL_ASSERT(mnWaitSymbolRequestCount>=0);
+
+ if (mnWaitSymbolRequestCount == 0)
+ {
+ if( !mpWaitSymbol )
+ {
+ // fall back to cursor
+ requestCursor(calcActiveCursor(mnCurrentCursor));
+ }
+ else
+ mpWaitSymbol->hide();
+ }
+}
+
+sal_Int16 SlideShowImpl::calcActiveCursor( sal_Int16 nCursorShape ) const
+{
+ if( mnWaitSymbolRequestCount>0 && !mpWaitSymbol ) // enforce wait cursor
+ nCursorShape = awt::SystemPointer::WAIT;
+ else if( !mbMouseVisible ) // enforce INVISIBLE
+ nCursorShape = awt::SystemPointer::INVISIBLE;
+ else if( maUserPaintColor &&
+ nCursorShape == awt::SystemPointer::ARROW )
+ nCursorShape = awt::SystemPointer::PEN;
+
+ return nCursorShape;
+}
+
+
+void SlideShowImpl::stopShow()
+{
+ // Force-end running animation
+ // ===========================
+ if (mpCurrentSlide)
+ {
+ mpCurrentSlide->hide();
+ //Register polygons in the map
+ if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
+ maPolygons.erase(mpCurrentSlide->getXDrawPage());
+
+ maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
+ }
+
+ // clear all queues
+ maEventQueue.clear();
+ maActivitiesQueue.clear();
+
+ // Attention: we MUST clear the user event queue here,
+ // this is because the current slide might have registered
+ // shape events (click or enter/leave), which might
+ // otherwise dangle forever in the queue (because of the
+ // shared ptr nature). If someone needs to change this:
+ // somehow unregister those shapes at the user event queue
+ // on notifySlideEnded().
+ maUserEventQueue.clear();
+
+ // re-enable automatic effect advancement
+ // (maEventQueue.clear() above might have killed
+ // maEventMultiplexer's tick events)
+ if (mbAutomaticAdvancementMode)
+ {
+ // toggle automatic mode (enabling just again is
+ // ignored by EventMultiplexer)
+ maEventMultiplexer.setAutomaticMode( false );
+ maEventMultiplexer.setAutomaticMode( true );
+ }
+}
+
+
+
+class SlideShowImpl::PrefetchPropertiesFunc
+{
+public:
+ PrefetchPropertiesFunc( SlideShowImpl * that_,
+ bool& rbSkipAllMainSequenceEffects,
+ bool& rbSkipSlideTransition)
+ : mpSlideShowImpl(that_),
+ mrbSkipAllMainSequenceEffects(rbSkipAllMainSequenceEffects),
+ mrbSkipSlideTransition(rbSkipSlideTransition)
+ {}
+
+ void operator()( beans::PropertyValue const& rProperty ) const {
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("Prefetch") ))
+ {
+ uno::Sequence<uno::Any> seq;
+ if ((rProperty.Value >>= seq) && seq.getLength() == 2)
+ {
+ seq[0] >>= mpSlideShowImpl->mxPrefetchSlide;
+ seq[1] >>= mpSlideShowImpl->mxPrefetchAnimationNode;
+ }
+ }
+ else if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("SkipAllMainSequenceEffects") ))
+ {
+ rProperty.Value >>= mrbSkipAllMainSequenceEffects;
+ }
+ else if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("SkipSlideTransition") ))
+ {
+ rProperty.Value >>= mrbSkipSlideTransition;
+ }
+ else
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ rProperty.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+private:
+ SlideShowImpl *const mpSlideShowImpl;
+ bool& mrbSkipAllMainSequenceEffects;
+ bool& mrbSkipSlideTransition;
+};
+
+void SlideShowImpl::displaySlide(
+ uno::Reference<drawing::XDrawPage> const& xSlide,
+ uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
+ uno::Reference<animations::XAnimationNode> const& xRootNode,
+ uno::Sequence<beans::PropertyValue> const& rProperties )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return;
+
+ maEffectRewinder.setRootAnimationNode(xRootNode);
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+#ifdef ENABLE_PRESENTER_EXTRA_UI
+ mxDrawPagesSupplier = xDrawPages;
+#else
+ mxDrawPagesSupplier = NULL;
+#endif
+
+ stopShow(); // MUST call that: results in
+ // maUserEventQueue.clear(). What's more,
+ // stopShow()'s currSlide->hide() call is
+ // now also required, notifySlideEnded()
+ // relies on that
+ // unconditionally. Otherwise, genuine
+ // shape animations (drawing layer and
+ // GIF) will not be stopped.
+
+ bool bSkipAllMainSequenceEffects (false);
+ bool bSkipSlideTransition (false);
+ std::for_each( rProperties.getConstArray(),
+ rProperties.getConstArray() + rProperties.getLength(),
+ PrefetchPropertiesFunc(this, bSkipAllMainSequenceEffects, bSkipSlideTransition) );
+
+ OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
+ if (maViewContainer.empty())
+ return;
+
+ // this here might take some time
+ {
+ WaitSymbolLock aLock (*this);
+
+ mpPreviousSlide = mpCurrentSlide;
+ mpCurrentSlide.reset();
+
+ if (matches( mpPrefetchSlide, xSlide, xRootNode ))
+ {
+ // prefetched slide matches:
+ mpCurrentSlide = mpPrefetchSlide;
+ }
+ else
+ mpCurrentSlide = makeSlide( xSlide, xDrawPages, xRootNode );
+
+ OSL_ASSERT( mpCurrentSlide );
+ if (mpCurrentSlide)
+ {
+ basegfx::B2DSize oldSlideSize;
+ if( mpPreviousSlide )
+ oldSlideSize = mpPreviousSlide->getSlideSize();
+
+ basegfx::B2DSize const slideSize( mpCurrentSlide->getSlideSize() );
+
+ // push new transformation to all views, if size changed
+ if( !mpPreviousSlide || oldSlideSize != slideSize )
+ {
+ std::for_each( maViewContainer.begin(),
+ maViewContainer.end(),
+ boost::bind( &View::setViewSize, _1,
+ boost::cref(slideSize) ));
+
+ // explicitly notify view change here,
+ // because transformation might have changed:
+ // optimization, this->notifyViewChange() would
+ // repaint slide which is not necessary.
+ maEventMultiplexer.notifyViewsChanged();
+ }
+
+ // create slide transition, and add proper end event
+ // (which then starts the slide effects
+ // via CURRENT_SLIDE.show())
+ ActivitySharedPtr pSlideChangeActivity (
+ createSlideTransition(
+ mpCurrentSlide->getXDrawPage(),
+ mpPreviousSlide,
+ mpCurrentSlide,
+ makeEvent(
+ boost::bind(
+ &SlideShowImpl::notifySlideTransitionEnded,
+ this,
+ false ),
+ "SlideShowImpl::notifySlideTransitionEnded")));
+
+ if (bSkipSlideTransition)
+ {
+ // The transition activity was created for the side effects
+ // (like sound transitions). Because we want to skip the
+ // acutual transition animation we do not need the activity
+ // anymore.
+ pSlideChangeActivity.reset();
+ }
+
+ if (pSlideChangeActivity)
+ {
+ // factory generated a slide transition - activate it!
+ maActivitiesQueue.addActivity( pSlideChangeActivity );
+ }
+ else
+ {
+ // no transition effect on this slide - schedule slide
+ // effect start event right away.
+ maEventQueue.addEvent(
+ makeEvent(
+ boost::bind(
+ &SlideShowImpl::notifySlideTransitionEnded,
+ this,
+ true ),
+ "SlideShowImpl::notifySlideTransitionEnded"));
+ }
+ }
+ } // finally
+
+ maEventMultiplexer.notifySlideTransitionStarted();
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
+
+ // We are currently rewinding an effect. This lead us from the next
+ // slide to this one. To complete this we have to play back all main
+ // sequence effects on this slide.
+ if (bSkipAllMainSequenceEffects)
+ maEffectRewinder.skipAllMainSequenceEffects();
+}
+
+void SlideShowImpl::redisplayCurrentSlide (void)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+ stopShow();
+
+ OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
+ if (maViewContainer.empty())
+ return;
+
+ // No transition effect on this slide - schedule slide
+ // effect start event right away.
+ maEventQueue.addEvent(
+ makeEvent(
+ boost::bind(
+ &SlideShowImpl::notifySlideTransitionEnded,
+ this,
+ true ),
+ "SlideShowImpl::notifySlideTransitionEnded"));
+
+ maEventMultiplexer.notifySlideTransitionStarted();
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
+}
+
+sal_Bool SlideShowImpl::nextEffect() throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ if (mbShowPaused)
+ return true;
+ else
+ return maEventMultiplexer.notifyNextEffect();
+}
+
+
+sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ if (mbShowPaused)
+ return true;
+ else
+ {
+ return maEffectRewinder.rewind(
+ maScreenUpdater.createLock(false),
+ ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::redisplayCurrentSlide), this),
+ ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::rewindEffectToPreviousSlide), this));
+ }
+}
+
+void SlideShowImpl::rewindEffectToPreviousSlide (void)
+{
+ // Show the wait symbol now and prevent it from showing temporary slide
+ // content while effects are played back.
+ WaitSymbolLock aLock (*this);
+
+ // A previous call to EffectRewinder::Rewind could not rewind the current
+ // effect because there are no effects on the current slide or none has
+ // yet been displayed. Go to the previous slide.
+ notifySlideEnded(true);
+
+ // Process pending events once more in order to have the following
+ // screen update show the last effect. Not sure whether this should be
+ // necessary.
+ maEventQueue.forceEmpty();
+
+ // We have to call the screen updater before the wait symbol is turned
+ // off. Otherwise the wait symbol would force the display of an
+ // intermediate state of the slide (before the effects are replayed.)
+ maScreenUpdater.commitUpdates();
+}
+
+sal_Bool SlideShowImpl::startShapeActivity(
+ uno::Reference<drawing::XShape> const& /*xShape*/ )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ // TODO(F3): NYI
+ OSL_ENSURE( false, "not yet implemented!" );
+ return false;
+}
+
+sal_Bool SlideShowImpl::stopShapeActivity(
+ uno::Reference<drawing::XShape> const& /*xShape*/ )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ // TODO(F3): NYI
+ OSL_ENSURE( false, "not yet implemented!" );
+ return false;
+}
+
+sal_Bool SlideShowImpl::pause( sal_Bool bPauseShow )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+
+ if (bPauseShow)
+ mpPresTimer->pauseTimer();
+ else
+ mpPresTimer->continueTimer();
+
+ maEventMultiplexer.notifyPauseMode(bPauseShow);
+
+ mbShowPaused = bPauseShow;
+ return true;
+}
+
+uno::Reference<drawing::XDrawPage> SlideShowImpl::getCurrentSlide()
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return uno::Reference<drawing::XDrawPage>();
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ if (mpCurrentSlide)
+ return mpCurrentSlide->getXDrawPage();
+ else
+ return uno::Reference<drawing::XDrawPage>();
+}
+
+sal_Bool SlideShowImpl::addView(
+ uno::Reference<presentation::XSlideShowView> const& xView )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ // first of all, check if view has a valid canvas
+ ENSURE_OR_RETURN_FALSE( xView.is(), "addView(): Invalid view" );
+ ENSURE_OR_RETURN_FALSE( xView->getCanvas().is(),
+ "addView(): View does not provide a valid canvas" );
+
+ UnoViewSharedPtr const pView( createSlideView(
+ xView,
+ maEventQueue,
+ maEventMultiplexer ));
+ if (!maViewContainer.addView( pView ))
+ return false; // view already added
+
+ // initialize view content
+ // =======================
+
+ if (mpCurrentSlide)
+ {
+ // set view transformation
+ const basegfx::B2ISize slideSize = mpCurrentSlide->getSlideSize();
+ pView->setViewSize( basegfx::B2DSize( slideSize.getX(),
+ slideSize.getY() ) );
+ }
+
+ // clear view area (since its newly added,
+ // we need a clean slate)
+ pView->clearAll();
+
+ // broadcast newly added view
+ maEventMultiplexer.notifyViewAdded( pView );
+
+ // set current mouse ptr
+ pView->setCursorShape( calcActiveCursor(mnCurrentCursor) );
+
+ return true;
+}
+
+sal_Bool SlideShowImpl::removeView(
+ uno::Reference<presentation::XSlideShowView> const& xView )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ ENSURE_OR_RETURN_FALSE( xView.is(), "removeView(): Invalid view" );
+
+ UnoViewSharedPtr const pView( maViewContainer.removeView( xView ) );
+ if( !pView )
+ return false; // view was not added in the first place
+
+ // remove view from EventMultiplexer (mouse events etc.)
+ maEventMultiplexer.notifyViewRemoved( pView );
+
+ pView->_dispose();
+
+ return true;
+}
+
+void SlideShowImpl::registerUserPaintPolygons( const uno::Reference< lang::XMultiServiceFactory >& xDocFactory ) throw (uno::RuntimeException)
+{
+ //Retrieve Polygons if user ends presentation by context menu
+ if (mpCurrentSlide)
+ {
+ if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
+ maPolygons.erase(mpCurrentSlide->getXDrawPage());
+
+ maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
+ }
+
+ //Creating the layer for shapes
+ // query for the XLayerManager
+ uno::Reference< drawing::XLayerSupplier > xLayerSupplier(xDocFactory, uno::UNO_QUERY);
+ uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
+
+ uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
+ // create a layer and set its properties
+ uno::Reference< drawing::XLayer > xDrawnInSlideshow = xLayerManager->insertNewByIndex(xLayerManager->getCount());
+ uno::Reference< beans::XPropertySet > xLayerPropSet(xDrawnInSlideshow, uno::UNO_QUERY);
+
+ //Layer Name which enables to catch annotations
+ rtl::OUString layerName = rtl::OUString::createFromAscii("DrawnInSlideshow");
+ uno::Any aPropLayer;
+
+ aPropLayer <<= layerName;
+ xLayerPropSet->setPropertyValue(rtl::OUString::createFromAscii("Name"), aPropLayer);
+
+ aPropLayer <<= true;
+ xLayerPropSet->setPropertyValue(rtl::OUString::createFromAscii("IsVisible"), aPropLayer);
+
+ aPropLayer <<= false;
+ xLayerPropSet->setPropertyValue(rtl::OUString::createFromAscii("IsLocked"), aPropLayer);
+
+ PolygonMap::iterator aIter=maPolygons.begin();
+
+ PolyPolygonVector aPolygons;
+ ::cppcanvas::PolyPolygonSharedPtr pPolyPoly;
+ ::basegfx::B2DPolyPolygon b2DPolyPoly;
+
+ //Register polygons for each slide
+ while(aIter!=maPolygons.end())
+ {
+ aPolygons = aIter->second;
+ //Get shapes for the slide
+ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > Shapes(aIter->first, ::com::sun::star::uno::UNO_QUERY);
+ //Retrieve polygons for one slide
+ for( PolyPolygonVector::iterator aIterPoly=aPolygons.begin(),
+ aEnd=aPolygons.end();
+ aIterPoly!=aEnd; ++aIterPoly )
+ {
+ pPolyPoly = (*aIterPoly);
+ b2DPolyPoly = ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(pPolyPoly->getUNOPolyPolygon());
+
+ //Normally there is only one polygon
+ for(sal_uInt32 i=0; i< b2DPolyPoly.count();i++)
+ {
+ const ::basegfx::B2DPolygon& aPoly = b2DPolyPoly.getB2DPolygon(i);
+ sal_uInt32 nPoints = aPoly.count();
+
+ if( nPoints > 1)
+ {
+ //create the PolyLineShape
+ uno::Reference< uno::XInterface > polyshape(xDocFactory->createInstance(
+ rtl::OUString::createFromAscii("com.sun.star.drawing.PolyLineShape") ) );
+ uno::Reference< drawing::XShape > rPolyShape(polyshape, uno::UNO_QUERY);
+
+ //Add the shape to the slide
+ Shapes->add(rPolyShape);
+
+ //Retrieve shape properties
+ uno::Reference< beans::XPropertySet > aXPropSet = uno::Reference< beans::XPropertySet >( rPolyShape, uno::UNO_QUERY );
+ //Construct a sequence of points sequence
+ drawing::PointSequenceSequence aRetval;
+ //Create only one sequence for one polygon
+ aRetval.realloc( 1 );
+ // Retrieve the sequence of points from aRetval
+ drawing::PointSequence* pOuterSequence = aRetval.getArray();
+ // Create 2 points in this sequence
+ pOuterSequence->realloc(nPoints);
+ // Get these points which are in an array
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+ for( sal_uInt32 n = 0; n < nPoints; n++ )
+ {
+ //Create a point from the polygon
+ *pInnerSequence++ = awt::Point(
+ basegfx::fround(aPoly.getB2DPoint(n).getX()),
+ basegfx::fround(aPoly.getB2DPoint(n).getY()));
+ }
+
+ //Fill the properties
+ //Give the built PointSequenceSequence.
+ uno::Any aParam;
+ aParam <<= aRetval;
+ aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("PolyPolygon"), aParam );
+
+ //LineStyle : SOLID by default
+ uno::Any aAny;
+ drawing::LineStyle eLS;
+ eLS = drawing::LineStyle_SOLID;
+ aAny <<= eLS;
+ aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("LineStyle"), aAny );
+
+ //LineColor
+ sal_uInt32 nLineColor;
+ nLineColor = pPolyPoly->getRGBALineColor();
+ //Transform polygon color from RRGGBBAA to AARRGGBB
+ aAny <<= RGBAColor2UnoColor(nLineColor);
+ aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("LineColor"), aAny );
+
+ //LineWidth
+ double fLineWidth;
+ fLineWidth = pPolyPoly->getStrokeWidth();
+ aAny <<= (sal_Int32)fLineWidth;
+ aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("LineWidth"), aAny );
+
+ // make polygons special
+ xLayerManager->attachShapeToLayer(rPolyShape, xDrawnInSlideshow);
+ }
+ }
+ }
+ ++aIter;
+ }
+}
+
+sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("AutomaticAdvancement") ))
+ {
+ double nTimeout(0.0);
+ mbAutomaticAdvancementMode = (rProperty.Value >>= nTimeout);
+ if (mbAutomaticAdvancementMode)
+ {
+ maEventMultiplexer.setAutomaticTimeout( nTimeout );
+ }
+ maEventMultiplexer.setAutomaticMode( mbAutomaticAdvancementMode );
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("UserPaintColor") ))
+ {
+ sal_Int32 nColor(0);
+ if (rProperty.Value >>= nColor)
+ {
+ OSL_ENSURE( mbMouseVisible,
+ "setProperty(): User paint overrides invisible mouse" );
+
+ // enable user paint
+ maUserPaintColor.reset( unoColor2RGBColor( nColor ) );
+ maEventMultiplexer.notifyUserPaintColor( *maUserPaintColor );
+ }
+ else
+ {
+ // disable user paint
+ maUserPaintColor.reset();
+ maEventMultiplexer.notifyUserPaintDisabled();
+ }
+
+ if( mnCurrentCursor == awt::SystemPointer::ARROW )
+ resetCursor();
+
+ return true;
+ }
+
+ //adding support for erasing features in UserPaintOverlay
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("EraseAllInk") ))
+ {
+ bool nEraseAllInk(false);
+ if (rProperty.Value >>= nEraseAllInk)
+ {
+ OSL_ENSURE( mbMouseVisible,
+ "setProperty(): User paint overrides invisible mouse" );
+
+ // enable user paint
+ maEraseAllInk.reset( nEraseAllInk );
+ maEventMultiplexer.notifyEraseAllInk( *maEraseAllInk );
+ }
+ else
+ {
+ // disable user paint
+ maEraseAllInk.reset();
+ maEventMultiplexer.notifyUserPaintDisabled();
+ }
+
+ if( mnCurrentCursor == awt::SystemPointer::ARROW )
+ resetCursor();
+
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("SwitchPenMode") ))
+ {
+ bool nSwitchPenMode(false);
+ if (rProperty.Value >>= nSwitchPenMode)
+ {
+ OSL_ENSURE( mbMouseVisible,
+ "setProperty(): User paint overrides invisible mouse" );
+
+ if(nSwitchPenMode == true){
+ // Switch to Pen Mode
+ maSwitchPenMode.reset( nSwitchPenMode );
+ maEventMultiplexer.notifySwitchPenMode();
+ }
+ }
+
+ if( mnCurrentCursor == awt::SystemPointer::ARROW )
+ resetCursor();
+ return true;
+ }
+
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("SwitchEraserMode") ))
+ {
+ bool nSwitchEraserMode(false);
+ if (rProperty.Value >>= nSwitchEraserMode)
+ {
+ OSL_ENSURE( mbMouseVisible,
+ "setProperty(): User paint overrides invisible mouse" );
+ if(nSwitchEraserMode == true){
+ // switch to Eraser mode
+ maSwitchEraserMode.reset( nSwitchEraserMode );
+ maEventMultiplexer.notifySwitchEraserMode();
+ }
+ }
+
+ if( mnCurrentCursor == awt::SystemPointer::ARROW )
+ resetCursor();
+ return true;
+ }
+
+
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("EraseInk") ))
+ {
+ sal_Int32 nEraseInk(100);
+ if (rProperty.Value >>= nEraseInk)
+ {
+ OSL_ENSURE( mbMouseVisible,
+ "setProperty(): User paint overrides invisible mouse" );
+
+ // enable user paint
+ maEraseInk.reset( nEraseInk );
+ maEventMultiplexer.notifyEraseInkWidth( *maEraseInk );
+ }
+ else
+ {
+ // disable user paint
+ maEraseInk.reset();
+ maEventMultiplexer.notifyUserPaintDisabled();
+ }
+
+ if( mnCurrentCursor == awt::SystemPointer::ARROW )
+ resetCursor();
+
+ return true;
+ }
+
+ // new Property for pen's width
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("UserPaintStrokeWidth") ))
+ {
+ double nWidth(4.0);
+ if (rProperty.Value >>= nWidth)
+ {
+ OSL_ENSURE( mbMouseVisible,"setProperty(): User paint overrides invisible mouse" );
+ // enable user paint stroke width
+ maUserPaintStrokeWidth.reset( nWidth );
+ maEventMultiplexer.notifyUserPaintStrokeWidth( *maUserPaintStrokeWidth );
+ }
+ else
+ {
+ // disable user paint stroke width
+ maUserPaintStrokeWidth.reset();
+ maEventMultiplexer.notifyUserPaintDisabled();
+ }
+ if( mnCurrentCursor == awt::SystemPointer::ARROW )
+ resetCursor();
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("AdvanceOnClick") ))
+ {
+ sal_Bool bAdvanceOnClick = sal_False;
+ if (! (rProperty.Value >>= bAdvanceOnClick))
+ return false;
+ maUserEventQueue.setAdvanceOnClick( bAdvanceOnClick );
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("DisableAnimationZOrder") ))
+ {
+ sal_Bool bDisableAnimationZOrder = sal_False;
+ if (! (rProperty.Value >>= bDisableAnimationZOrder))
+ return false;
+ mbDisableAnimationZOrder = bDisableAnimationZOrder == sal_True;
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("ImageAnimationsAllowed") ) )
+ {
+ if (! (rProperty.Value >>= mbImageAnimationsAllowed))
+ return false;
+
+ // TODO(F3): Forward to slides!
+// if( bOldValue != mbImageAnimationsAllowed )
+// {
+// if( mbImageAnimationsAllowed )
+// maEventMultiplexer.notifyIntrinsicAnimationsEnabled();
+// else
+// maEventMultiplexer.notifyIntrinsicAnimationsDisabled();
+// }
+
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("MouseVisible") ))
+ {
+ if (! (rProperty.Value >>= mbMouseVisible))
+ return false;
+
+ requestCursor(mnCurrentCursor);
+
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("ForceManualAdvance") ))
+ {
+ return (rProperty.Value >>= mbForceManualAdvance);
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("RehearseTimings") ))
+ {
+ bool bRehearseTimings = false;
+ if (! (rProperty.Value >>= bRehearseTimings))
+ return false;
+
+ if (bRehearseTimings)
+ {
+ // TODO(Q3): Move to slide
+ mpRehearseTimingsActivity = RehearseTimingsActivity::create(
+ SlideShowContext(
+ mpDummyPtr,
+ maEventQueue,
+ maEventMultiplexer,
+ maScreenUpdater,
+ maActivitiesQueue,
+ maUserEventQueue,
+ *this,
+ maViewContainer,
+ mxComponentContext) );
+ }
+ else if (mpRehearseTimingsActivity)
+ {
+ // removes timer from all views:
+ mpRehearseTimingsActivity->dispose();
+ mpRehearseTimingsActivity.reset();
+ }
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("WaitSymbolBitmap") ))
+ {
+ uno::Reference<rendering::XBitmap> xBitmap;
+ if (! (rProperty.Value >>= xBitmap))
+ return false;
+
+ mpWaitSymbol = WaitSymbol::create( xBitmap,
+ maScreenUpdater,
+ maEventMultiplexer,
+ maViewContainer );
+
+ return true;
+ }
+
+ if (rProperty.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("NoSlideTransitions") ))
+ {
+ return (rProperty.Value >>= mbNoSlideTransitions);
+ }
+
+ if (rProperty.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSoundEnabled")))
+ {
+ uno::Sequence<uno::Any> aValues;
+ uno::Reference<presentation::XSlideShowView> xView;
+ sal_Bool bValue (false);
+ if ((rProperty.Value >>= aValues)
+ && aValues.getLength()==2
+ && (aValues[0] >>= xView)
+ && (aValues[1] >>= bValue))
+ {
+ // Look up the view.
+ for (UnoViewVector::const_iterator
+ iView (maViewContainer.begin()),
+ iEnd (maViewContainer.end());
+ iView!=iEnd;
+ ++iView)
+ {
+ if (*iView && (*iView)->getUnoView()==xView)
+ {
+ // Store the flag at the view so that media shapes have
+ // access to it.
+ (*iView)->setIsSoundEnabled(bValue);
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void SlideShowImpl::addSlideShowListener(
+ uno::Reference<presentation::XSlideShowListener> const& xListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return;
+
+ // container syncs with passed mutex ref
+ maListenerContainer.addInterface(xListener);
+}
+
+void SlideShowImpl::removeSlideShowListener(
+ uno::Reference<presentation::XSlideShowListener> const& xListener )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // container syncs with passed mutex ref
+ maListenerContainer.removeInterface(xListener);
+}
+
+void SlideShowImpl::addShapeEventListener(
+ uno::Reference<presentation::XShapeEventListener> const& xListener,
+ uno::Reference<drawing::XShape> const& xShape )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ ShapeEventListenerMap::iterator aIter;
+ if( (aIter=maShapeEventListeners.find( xShape )) ==
+ maShapeEventListeners.end() )
+ {
+ // no entry for this shape -> create one
+ aIter = maShapeEventListeners.insert(
+ ShapeEventListenerMap::value_type(
+ xShape,
+ boost::shared_ptr<cppu::OInterfaceContainerHelper>(
+ new cppu::OInterfaceContainerHelper(m_aMutex)))).first;
+ }
+
+ // add new listener to broadcaster
+ if( aIter->second.get() )
+ aIter->second->addInterface( xListener );
+
+ maEventMultiplexer.notifyShapeListenerAdded(xListener,
+ xShape);
+}
+
+void SlideShowImpl::removeShapeEventListener(
+ uno::Reference<presentation::XShapeEventListener> const& xListener,
+ uno::Reference<drawing::XShape> const& xShape )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ ShapeEventListenerMap::iterator aIter;
+ if( (aIter = maShapeEventListeners.find( xShape )) !=
+ maShapeEventListeners.end() )
+ {
+ // entry for this shape found -> remove listener from
+ // helper object
+ ENSURE_OR_THROW(
+ aIter->second.get(),
+ "SlideShowImpl::removeShapeEventListener(): "
+ "listener map contains NULL broadcast helper" );
+
+ aIter->second->removeInterface( xListener );
+ }
+
+ maEventMultiplexer.notifyShapeListenerRemoved(xListener,
+ xShape);
+}
+
+void SlideShowImpl::setShapeCursor(
+ uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return;
+
+ // precondition: must only be called from the main thread!
+ DBG_TESTSOLARMUTEX();
+
+ ShapeCursorMap::iterator aIter;
+ if( (aIter=maShapeCursors.find( xShape )) == maShapeCursors.end() )
+ {
+ // no entry for this shape -> create one
+ if( nPointerShape != awt::SystemPointer::ARROW )
+ {
+ // add new entry, unless shape shall display
+ // normal pointer arrow -> no need to handle that
+ // case
+ maShapeCursors.insert(
+ ShapeCursorMap::value_type(xShape,
+ nPointerShape) );
+ }
+ }
+ else if( nPointerShape == awt::SystemPointer::ARROW )
+ {
+ // shape shall display normal cursor -> can disable
+ // the cursor and clear the entry
+ maShapeCursors.erase( xShape );
+ }
+ else
+ {
+ // existing entry found, update with new cursor ID
+ aIter->second = nPointerShape;
+ }
+
+ maEventMultiplexer.notifyShapeCursorChange(xShape,
+ nPointerShape);
+}
+
+bool SlideShowImpl::requestCursor( sal_Int16 nCursorShape )
+{
+ mnCurrentCursor = nCursorShape;
+
+ const sal_Int16 nActualCursor = calcActiveCursor(mnCurrentCursor);
+
+ // change all views to the requested cursor ID
+ std::for_each( maViewContainer.begin(),
+ maViewContainer.end(),
+ boost::bind( &View::setCursorShape,
+ _1,
+ nActualCursor ));
+
+ return nActualCursor==nCursorShape;
+}
+
+void SlideShowImpl::resetCursor()
+{
+ mnCurrentCursor = awt::SystemPointer::ARROW;
+
+ // change all views to the default cursor ID
+ std::for_each( maViewContainer.begin(),
+ maViewContainer.end(),
+ boost::bind( &View::setCursorShape,
+ _1,
+ calcActiveCursor(mnCurrentCursor) ));
+}
+
+sal_Bool SlideShowImpl::update( double & nNextTimeout )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ // precondition: update() must only be called from the
+ // main thread!
+ DBG_TESTSOLARMUTEX();
+
+ if( mbShowPaused )
+ {
+ // commit frame (might be repaints pending)
+ maScreenUpdater.commitUpdates();
+
+ return false;
+ }
+ else
+ {
+ // TODO(F2): re-evaluate whether that timer lagging makes
+ // sense.
+
+ // hold timer, while processing the queues:
+ // 1. when there is more than one active activity this ensures the
+ // same time for all activities and events
+ // 2. processing of events may lead to creation of further events
+ // that have zero delay. While the timer is stopped these events
+ // are processed in the same run.
+ {
+ comphelper::ScopeGuard scopeGuard(
+ boost::bind( &canvas::tools::ElapsedTime::releaseTimer,
+ boost::cref(mpPresTimer) ) );
+ mpPresTimer->holdTimer();
+
+ // process queues
+ maEventQueue.process();
+ maActivitiesQueue.process();
+
+ // commit frame to screen
+ maFrameSynchronization.Synchronize();
+ maScreenUpdater.commitUpdates();
+
+ // TODO(Q3): remove need to call dequeued() from
+ // activities. feels like a wart.
+ //
+ // Rationale for ActivitiesQueue::processDequeued(): when
+ // an activity ends, it usually pushed the end state to
+ // the animated shape in question, and ends the animation
+ // (which, in turn, will usually disable shape sprite
+ // mode). Disabling shape sprite mode causes shape
+ // repaint, which, depending on slide content, takes
+ // considerably more time than sprite updates. Thus, the
+ // last animation step tends to look delayed. To
+ // camouflage this, reaching end position and disabling
+ // sprite mode is split into two (normal Activity::end(),
+ // and Activity::dequeued()). Now, the reason to call
+ // commitUpdates() twice here is caused by the unrelated
+ // fact that during wait cursor display/hide, the screen
+ // is updated, and shows hidden sprites, but, in case of
+ // leaving the second commitUpdates() call out and punting
+ // that to the next round, no updated static slide
+ // content. In short, the last shape animation of a slide
+ // tends to blink at its end.
+
+ // process dequeued activities _after_ commit to screen
+ maActivitiesQueue.processDequeued();
+
+ // commit frame to screen
+ maScreenUpdater.commitUpdates();
+ }
+ // Time held until here
+
+ const bool bActivitiesLeft = (! maActivitiesQueue.isEmpty());
+ const bool bTimerEventsLeft = (! maEventQueue.isEmpty());
+ const bool bRet = (bActivitiesLeft || bTimerEventsLeft);
+
+ if (bRet)
+ {
+ // calc nNextTimeout value:
+ if (bActivitiesLeft)
+ {
+ // Activity queue is not empty. Tell caller that we would
+ // like to render another frame.
+
+ // Return a zero time-out to signal our caller to call us
+ // back as soon as possible. The actual timing, waiting the
+ // appropriate amount of time between frames, is then done
+ // by the maFrameSynchronization object.
+ nNextTimeout = 0;
+ maFrameSynchronization.Activate();
+ }
+ else
+ {
+ // timer events left:
+ // difference from current time (nota bene:
+ // time no longer held here!) to the next event in
+ // the event queue.
+
+ // #i61190# Retrieve next timeout only _after_
+ // processing activity queue
+
+ // ensure positive value:
+ nNextTimeout = std::max( 0.0, maEventQueue.nextTimeout() );
+
+ // There is no active animation so the frame rate does not
+ // need to be synchronized.
+ maFrameSynchronization.Deactivate();
+ }
+
+ mbSlideShowIdle = false;
+ }
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ // when slideshow is idle, issue an XUpdatable::update() call
+ // exactly once after a previous animation sequence finished -
+ // this might trigger screen dumps on some canvas
+ // implementations
+ if( !mbSlideShowIdle &&
+ (!bRet ||
+ nNextTimeout > 1.0) )
+ {
+ UnoViewVector::const_iterator aCurr(maViewContainer.begin());
+ const UnoViewVector::const_iterator aEnd(maViewContainer.end());
+ while( aCurr != aEnd )
+ {
+ try
+ {
+ uno::Reference< presentation::XSlideShowView > xView( (*aCurr)->getUnoView(),
+ uno::UNO_QUERY_THROW );
+ uno::Reference< util::XUpdatable > xUpdatable( xView->getCanvas(),
+ uno::UNO_QUERY_THROW );
+ xUpdatable->update();
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+ ++aCurr;
+ }
+
+ mbSlideShowIdle = true;
+ }
+#endif
+
+ return bRet;
+ }
+}
+
+void SlideShowImpl::notifySlideTransitionEnded( bool bPaintSlide )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ OSL_ENSURE( !isDisposed(), "### already disposed!" );
+ OSL_ENSURE( mpCurrentSlide,
+ "notifySlideTransitionEnded(): Invalid current slide" );
+ if (mpCurrentSlide)
+ {
+ // first init show, to give the animations
+ // the chance to register SlideStartEvents
+ const bool bBackgroundLayerRendered( !bPaintSlide );
+ mpCurrentSlide->show( bBackgroundLayerRendered );
+ maEventMultiplexer.notifySlideStartEvent();
+ }
+}
+
+void queryAutomaticSlideTransition( uno::Reference<drawing::XDrawPage> const& xDrawPage,
+ double& nAutomaticNextSlideTimeout,
+ bool& bHasAutomaticNextSlide )
+{
+ // retrieve slide change parameters from XDrawPage
+ // ===============================================
+
+ uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
+ uno::UNO_QUERY );
+
+ sal_Int32 nChange(0);
+ if( !xPropSet.is() ||
+ !getPropertyValue( nChange,
+ xPropSet,
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Change"))) )
+ {
+ OSL_TRACE(
+ "queryAutomaticSlideTransition(): "
+ "Could not extract slide change mode from XDrawPage - assuming <none>\n" );
+ }
+
+ bHasAutomaticNextSlide = nChange == 1;
+
+ if( !xPropSet.is() ||
+ !getPropertyValue( nAutomaticNextSlideTimeout,
+ xPropSet,
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Duration"))) )
+ {
+ OSL_TRACE(
+ "queryAutomaticSlideTransition(): "
+ "Could not extract slide transition timeout from "
+ "XDrawPage - assuming 1 sec\n" );
+ }
+}
+
+void SlideShowImpl::notifySlideAnimationsEnded()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ //Draw polygons above animations
+ mpCurrentSlide->drawPolygons();
+
+ OSL_ENSURE( !isDisposed(), "### already disposed!" );
+
+ // This struct will receive the (interruptable) event,
+ // that triggers the notifySlideEnded() method.
+ InterruptableEventPair aNotificationEvents;
+
+ if( maEventMultiplexer.getAutomaticMode() )
+ {
+ OSL_ENSURE( ! mpRehearseTimingsActivity,
+ "unexpected: RehearseTimings mode!" );
+
+ // schedule a slide end event, with automatic mode's
+ // delay
+ aNotificationEvents = makeInterruptableDelay(
+ boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
+ maEventMultiplexer.getAutomaticTimeout() );
+ }
+ else
+ {
+ OSL_ENSURE( mpCurrentSlide,
+ "notifySlideAnimationsEnded(): Invalid current slide!" );
+
+ bool bHasAutomaticNextSlide=false;
+ double nAutomaticNextSlideTimeout=0.0;
+ queryAutomaticSlideTransition(mpCurrentSlide->getXDrawPage(),
+ nAutomaticNextSlideTimeout,
+ bHasAutomaticNextSlide);
+
+ // check whether slide transition should happen
+ // 'automatically'. If yes, simply schedule the
+ // specified timeout.
+ // NOTE: mbForceManualAdvance and mpRehearseTimingsActivity
+ // override any individual slide setting, to always
+ // step slides manually.
+ if( !mbForceManualAdvance &&
+ !mpRehearseTimingsActivity &&
+ bHasAutomaticNextSlide )
+ {
+ aNotificationEvents = makeInterruptableDelay(
+ boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
+ nAutomaticNextSlideTimeout);
+
+ // TODO(F2): Provide a mechanism to let the user override
+ // this automatic timeout via next()
+ }
+ else
+ {
+ if (mpRehearseTimingsActivity)
+ mpRehearseTimingsActivity->start();
+
+ // generate click event. Thus, the user must
+ // trigger the actual end of a slide. No need to
+ // generate interruptable event here, there's no
+ // timeout involved.
+ aNotificationEvents.mpImmediateEvent =
+ makeEvent( boost::bind<void>(
+ boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
+ "SlideShowImpl::notifySlideEnded");
+ }
+ }
+
+ // register events on the queues. To make automatic slide
+ // changes interruptable, register the interruption event
+ // as a nextEffectEvent target. Note that the timeout
+ // event is optional (e.g. manual slide changes don't
+ // generate a timeout)
+ maUserEventQueue.registerNextEffectEvent(
+ aNotificationEvents.mpImmediateEvent );
+
+ if( aNotificationEvents.mpTimeoutEvent )
+ maEventQueue.addEvent( aNotificationEvents.mpTimeoutEvent );
+
+ // current slide's main sequence is over. Now should be
+ // the time to prefetch the next slide (if any), and
+ // prepare the initial slide bitmap (speeds up slide
+ // change setup time a lot). Show the wait cursor, this
+ // indeed might take some seconds.
+ {
+ WaitSymbolLock aLock (*this);
+
+ if (! matches( mpPrefetchSlide,
+ mxPrefetchSlide, mxPrefetchAnimationNode ))
+ {
+ mpPrefetchSlide = makeSlide( mxPrefetchSlide, mxDrawPagesSupplier,
+ mxPrefetchAnimationNode );
+ }
+ if (mpPrefetchSlide)
+ {
+ // ignore return value, this is just to populate
+ // Slide's internal bitmap buffer, such that the time
+ // needed to generate the slide bitmap is not spent
+ // when the slide change is requested.
+ mpPrefetchSlide->getCurrentSlideBitmap( *maViewContainer.begin() );
+ }
+ } // finally
+
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::mem_fn( &presentation::XSlideShowListener::slideAnimationsEnded ) );
+}
+
+void SlideShowImpl::notifySlideEnded (const bool bReverse)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ OSL_ENSURE( !isDisposed(), "### already disposed!" );
+
+ if (mpRehearseTimingsActivity && !bReverse)
+ {
+ const double time = mpRehearseTimingsActivity->stop();
+ if (mpRehearseTimingsActivity->hasBeenClicked())
+ {
+ // save time at current drawpage:
+ uno::Reference<beans::XPropertySet> xPropSet(
+ mpCurrentSlide->getXDrawPage(), uno::UNO_QUERY );
+ OSL_ASSERT( xPropSet.is() );
+ if (xPropSet.is())
+ {
+ xPropSet->setPropertyValue(
+ OUSTR("Change"),
+ uno::Any( static_cast<sal_Int32>(1) ) );
+ xPropSet->setPropertyValue(
+ OUSTR("Duration"),
+ uno::Any( static_cast<sal_Int32>(time) ) );
+ }
+ }
+ }
+
+ if (bReverse)
+ maEventMultiplexer.notifySlideEndEvent();
+
+ stopShow(); // MUST call that: results in
+ // maUserEventQueue.clear(). What's more,
+ // stopShow()'s currSlide->hide() call is
+ // now also required, notifySlideEnded()
+ // relies on that
+ // unconditionally. Otherwise, genuine
+ // shape animations (drawing layer and
+ // GIF) will not be stopped.
+
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::bind<void>(
+ ::boost::mem_fn(&presentation::XSlideShowListener::slideEnded),
+ _1,
+ sal_Bool(bReverse)));
+}
+
+bool SlideShowImpl::notifyHyperLinkClicked( rtl::OUString const& hyperLink )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::bind( &presentation::XSlideShowListener::hyperLinkClicked,
+ _1,
+ boost::cref(hyperLink) ));
+ return true;
+}
+
+/** Notification from eventmultiplexer that an animation event has occoured.
+ This will be forewarded to all registered XSlideShoeListener
+ */
+bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ uno::Reference<animations::XAnimationNode> xNode( rNode->getXAnimationNode() );
+
+ switch( rNode->getState() )
+ {
+ case AnimationNode::ACTIVE:
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::bind( &animations::XAnimationListener::beginEvent,
+ _1,
+ boost::cref(xNode) ));
+ break;
+
+ case AnimationNode::FROZEN:
+ case AnimationNode::ENDED:
+ maListenerContainer.forEach<presentation::XSlideShowListener>(
+ boost::bind( &animations::XAnimationListener::endEvent,
+ _1,
+ boost::cref(xNode) ));
+ if(mpCurrentSlide->isPaintOverlayActive())
+ mpCurrentSlide->drawPolygons();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+
+//===== FrameSynchronization ==================================================
+
+FrameSynchronization::FrameSynchronization (const double nFrameDuration)
+ : maTimer(),
+ mnFrameDuration(nFrameDuration),
+ mnNextFrameTargetTime(0),
+ mbIsActive(false)
+{
+ MarkCurrentFrame();
+}
+
+
+
+
+void FrameSynchronization::MarkCurrentFrame (void)
+{
+ mnNextFrameTargetTime = maTimer.getElapsedTime() + mnFrameDuration;
+}
+
+
+
+
+void FrameSynchronization::Synchronize (void)
+{
+ if (mbIsActive)
+ {
+ // Do busy waiting for now.
+ while (maTimer.getElapsedTime() < mnNextFrameTargetTime)
+ ;
+ }
+
+ MarkCurrentFrame();
+}
+
+
+
+
+void FrameSynchronization::Activate (void)
+{
+ mbIsActive = true;
+}
+
+
+
+
+void FrameSynchronization::Deactivate (void)
+{
+ mbIsActive = false;
+}
+
+
+
+
+double FrameSynchronization::GetCurrentTime (void) const
+{
+ return maTimer.getElapsedTime();
+}
+
+
+} // anon namespace
+
+namespace sdecl = comphelper::service_decl;
+#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+ sdecl::class_<SlideShowImpl> serviceImpl;
+ const sdecl::ServiceDecl slideShowDecl(
+ serviceImpl,
+#else
+ const sdecl::ServiceDecl slideShowDecl(
+ sdecl::class_<SlideShowImpl>(),
+#endif
+ "com.sun.star.comp.presentation.SlideShow",
+ "com.sun.star.presentation.SlideShow" );
+
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(slideShowDecl)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/slideview.cxx b/slideshow/source/engine/slideview.cxx
new file mode 100644
index 000000000000..376b8a3f7249
--- /dev/null
+++ b/slideshow/source/engine/slideview.cxx
@@ -0,0 +1,1198 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/canvastools.hxx>
+
+#include "eventqueue.hxx"
+#include "eventmultiplexer.hxx"
+#include "slideview.hxx"
+#include "delayevent.hxx"
+#include "unoview.hxx"
+
+#include <rtl/instance.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase2.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <comphelper/make_shared_from_uno.hxx>
+
+#include <cppcanvas/spritecanvas.hxx>
+#include <cppcanvas/customsprite.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include <tools/debug.hxx>
+
+#include <basegfx/range/b1drange.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+
+#include <com/sun/star/presentation/XSlideShow.hpp>
+
+#include <boost/noncopyable.hpp>
+#include <boost/bind.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include <vector>
+#include <iterator>
+#include <algorithm>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+struct StaticUnitRectPoly : public rtl::StaticWithInit<basegfx::B2DPolygon, StaticUnitRectPoly>
+{
+ basegfx::B2DPolygon operator()()
+ {
+ return basegfx::tools::createUnitPolygon();
+ }
+};
+
+/** Sprite entry, to store sprite plus priority
+
+ The operator<() defines a strict weak ordering of sprites, sort
+ key is the sprite priority.
+ */
+struct SpriteEntry
+{
+ SpriteEntry( const cppcanvas::CustomSpriteSharedPtr& rSprite,
+ double nPrio ) :
+ mpSprite( rSprite ),
+ mnPriority( nPrio )
+ {
+ }
+
+ bool operator<(const SpriteEntry& rRHS) const
+ {
+ return mnPriority < rRHS.mnPriority;
+ }
+
+ boost::weak_ptr< cppcanvas::CustomSprite > mpSprite;
+ double mnPriority;
+};
+
+typedef std::vector< SpriteEntry > SpriteVector;
+
+
+/** Create a clip polygon for slide views
+
+ @param rClip
+ Clip to set (can be empty)
+
+ @param rCanvas
+ Canvas to create the clip polygon for
+
+ @param rUserSize
+ The size of the view. Note that the returned clip will
+ <em>always</em> clip to at least the rect defined herein.
+
+ @return the view clip polygon, in view coordinates, which is
+ guaranteed to at least clip to the view size.
+ */
+basegfx::B2DPolyPolygon createClipPolygon( const basegfx::B2DPolyPolygon& rClip,
+ const cppcanvas::CanvasSharedPtr& /*rCanvas*/,
+ const basegfx::B2DSize& rUserSize )
+{
+ // setup canvas clipping
+ // =====================
+
+ // AW: Simplified
+ const basegfx::B2DRange aClipRange(0, 0, rUserSize.getX(), rUserSize.getY());
+
+ if(rClip.count())
+ {
+ return basegfx::tools::clipPolyPolygonOnRange(rClip, aClipRange, true, false);
+ }
+ else
+ {
+ return basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aClipRange));
+ }
+}
+
+/** Prepare given clip polygon to be stored as the current clip
+
+ Note that this is separate from createClipPolygon(), to allow
+ SlideView implementations to store this intermediate result
+ (createClipPolygon() has to be called every time the view size
+ changes)
+ */
+basegfx::B2DPolyPolygon prepareClip( const basegfx::B2DPolyPolygon& rClip )
+{
+ basegfx::B2DPolyPolygon aClip( rClip );
+
+ // TODO(P2): unnecessary, once XCanvas is correctly handling this
+ // AW: Should be no longer necessary; tools are now bezier-safe
+ if( aClip.areControlPointsUsed() )
+ aClip = basegfx::tools::adaptiveSubdivideByAngle( aClip );
+
+ // normalize polygon, preparation for clipping
+ // in updateCanvas()
+ aClip = basegfx::tools::correctOrientations(aClip);
+ aClip = basegfx::tools::solveCrossovers(aClip);
+ aClip = basegfx::tools::stripNeutralPolygons(aClip);
+ aClip = basegfx::tools::stripDispensablePolygons(aClip, false);
+
+ return aClip;
+}
+
+
+void clearRect( ::cppcanvas::CanvasSharedPtr const& pCanvas,
+ basegfx::B2IRange const& rArea )
+{
+ // convert clip polygon to device coordinate system
+ ::basegfx::B2DPolyPolygon const* pClipPoly( pCanvas->getClip() );
+ if( pClipPoly )
+ {
+ ::basegfx::B2DPolyPolygon aClipPoly( *pClipPoly );
+ aClipPoly.transform( pCanvas->getTransformation() );
+ pCanvas->setClip( aClipPoly );
+ }
+
+ // set transformation to identitiy (->device pixel)
+ pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // #i42440# Fill the _full_ background in
+ // black. Since we had to extend the bitmap by one
+ // pixel, and the bitmap is initialized white,
+ // depending on the slide content a one pixel wide
+ // line will show to the bottom and the right.
+ const ::basegfx::B2DPolygon aPoly(
+ ::basegfx::tools::createPolygonFromRect(
+ basegfx::B2DRange(rArea)));
+
+ ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
+ ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCanvas,
+ aPoly ) );
+
+ if( pPolyPoly )
+ {
+ pPolyPoly->setCompositeOp( cppcanvas::CanvasGraphic::SOURCE );
+ pPolyPoly->setRGBAFillColor( 0x00000000U );
+ pPolyPoly->draw();
+ }
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ ::cppcanvas::CanvasSharedPtr pCliplessCanvas( pCanvas->clone() );
+ pCliplessCanvas->setClip();
+
+ if( pCanvas->getClip() )
+ {
+ ::cppcanvas::PolyPolygonSharedPtr pPolyPoly2(
+ ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCliplessCanvas,
+ *(pCanvas->getClip()) ));
+ if( pPolyPoly2 )
+ {
+ pPolyPoly2->setRGBALineColor( 0x008000FFU );
+ pPolyPoly2->draw();
+ }
+ }
+#endif
+}
+
+/** Get bounds in pixel
+
+ @param rLayerBounds
+ Bound rect, in user space coordinates
+
+ @param rTransformation
+ User space to device pixel transformation
+
+ @return the layer bounds in pixel, extended by one pixel to the
+ right and bottom
+ */
+basegfx::B2IRange getLayerBoundsPixel( basegfx::B2DRange const& rLayerBounds,
+ basegfx::B2DHomMatrix const& rTransformation )
+{
+ ::basegfx::B2DRange aTmpRect;
+ ::canvas::tools::calcTransformedRectBounds( aTmpRect,
+ rLayerBounds,
+ rTransformation );
+
+ if( aTmpRect.isEmpty() )
+ return ::basegfx::B2IRange();
+
+ // #i42440# Returned layer size is one pixel too small, as
+ // rendering happens one pixel to the right and below the
+ // actual bound rect.
+ return ::basegfx::B2IRange( ::basegfx::fround(aTmpRect.getMinX()),
+ ::basegfx::fround(aTmpRect.getMinY()),
+ ::basegfx::fround(aTmpRect.getMaxX()) + 1,
+ ::basegfx::fround(aTmpRect.getMaxY()) + 1 );
+}
+
+
+// ----------------------------------------------------------------
+
+/** Container class for sprites issued by a ViewLayer
+
+ This class handles the sprite prioritization issues, that are
+ needed for layer sprites (e.g. the need to re-prioritize sprites
+ when the layer changes prio).
+ */
+class LayerSpriteContainer
+{
+ /** Max fill level of maSprites, before we try to prune it from
+ deceased sprites
+ */
+ enum{ SPRITE_ULLAGE=256 };
+
+ /** All sprites that have been issued by this container (pruned
+ from time to time, for invalid references). This vector is
+ kept sorted with increasing sprite priority.
+ */
+ SpriteVector maSprites;
+
+ /// Priority of this layer, relative to other view layers
+ basegfx::B1DRange maLayerPrioRange;
+
+ double getSpritePriority( std::size_t nSpriteNum ) const
+ {
+ // divide the available layer range equally between all
+ // sprites, assign upper bound of individual sprite range as
+ // sprite prio (the layer itself gets assigned the lower bound
+ // of sprite 0's individual range):
+ //
+ // | layer 0 | layer 1 | ...
+ // | sprite 0 | sprite 1 | sprite 0 | sprite 1 | ...
+ return maLayerPrioRange.getMinimum() + maLayerPrioRange.getRange()*(nSpriteNum+1)/(maSprites.size()+1);
+ }
+
+ /** Rescan sprite vector, and remove deceased sprites (and reset
+ sprite prio)
+
+ @param aBegin
+ Iterator to the first entry to rescan
+ */
+ void updateSprites()
+ {
+ SpriteVector aValidSprites;
+
+ // check all sprites for validity and set new priority
+ SpriteVector::iterator aCurrSprite( maSprites.begin() );
+ const SpriteVector::iterator aEnd( maSprites.end() );
+ while( aCurrSprite != aEnd )
+ {
+ cppcanvas::CustomSpriteSharedPtr pCurrSprite( aCurrSprite->mpSprite.lock() );
+
+ if( pCurrSprite )
+ {
+ // only copy still valid sprites over to the refreshed
+ // sprite vector.
+ aValidSprites.push_back( *aCurrSprite );
+
+ pCurrSprite->setPriority(
+ getSpritePriority( aValidSprites.size()-1 ));
+ }
+
+ ++aCurrSprite;
+ }
+
+ // replace sprite list with pruned one
+ maSprites.swap( aValidSprites );
+ }
+
+public:
+ LayerSpriteContainer() :
+ maSprites(),
+ maLayerPrioRange()
+ {
+ }
+
+ basegfx::B1DRange getLayerPriority() const
+ {
+ return maLayerPrioRange;
+ }
+
+ void setLayerPriority( const basegfx::B1DRange& rRange )
+ {
+ if( rRange != maLayerPrioRange )
+ {
+ maLayerPrioRange = rRange;
+
+ // prune and recalc sprite prios
+ updateSprites();
+ }
+ }
+
+ void addSprite( const cppcanvas::CustomSpriteSharedPtr& pSprite,
+ double nPriority )
+ {
+ if( !pSprite )
+ return;
+
+ SpriteEntry aEntry( pSprite,nPriority );
+
+ // insert new sprite, such that vector stays sorted
+ SpriteVector::iterator aInsertPos(
+ maSprites.insert(
+ std::lower_bound( maSprites.begin(),
+ maSprites.end(),
+ aEntry ),
+ aEntry ));
+
+ const std::size_t nNumSprites( maSprites.size() );
+ if( nNumSprites > SPRITE_ULLAGE ||
+ maSprites.end() - aInsertPos > 1 )
+ {
+ // updateSprites() also updates all sprite prios
+ updateSprites();
+ }
+ else
+ {
+ // added sprite to the end, and not too many sprites in
+ // vector - perform optimized update (only need to set
+ // prio). This basically caters for the common case of
+ // iterated character animations, which generate lots of
+ // sprites, all added to the end.
+ pSprite->setPriority(
+ getSpritePriority( nNumSprites-1 ));
+ }
+ }
+
+ void clear()
+ {
+ maSprites.clear();
+ }
+};
+
+
+// ----------------------------------------------------------------
+
+
+/** This class provides layers for a slide view
+
+ Layers are used to render animations with the correct z order -
+ because sprites are always in front of the static canvas
+ background, shapes that must appear <em<before</em> an animation
+ must also be displayed as a sprite.
+
+ Each layer has a priority assigned to it (valid range [0,1]), which
+ also affects all sprites created for this specific layer - i.e. if
+ the layer priority changes, the sprites change z order together
+ with their parent.
+ */
+class SlideViewLayer : public ViewLayer,
+ private boost::noncopyable
+{
+ /// Smart container for all sprites issued by this layer
+ mutable LayerSpriteContainer maSpriteContainer;
+
+ /// Bounds of this layer in user space coordinates
+ basegfx::B2DRange maLayerBounds;
+
+ /// Bounds of this layer in device pixel
+ mutable basegfx::B2IRange maLayerBoundsPixel;
+
+ /// Current clip polygon in user coordinates
+ basegfx::B2DPolyPolygon maClip;
+
+ /// Current size of the view in user coordinates
+ basegfx::B2DSize maUserSize;
+
+ /// Current overall view transformation
+ basegfx::B2DHomMatrix maTransformation;
+
+ /// 'parent' canvas, this viewlayer is associated with
+ const cppcanvas::SpriteCanvasSharedPtr mpSpriteCanvas;
+
+ /** output surface (necessarily a sprite, won't otherwise be able
+ to display anything <em>before</em> other sprites)
+ */
+ mutable cppcanvas::CustomSpriteSharedPtr mpSprite;
+
+ /// actual output canvas retrieved from a sprite
+ mutable cppcanvas::CanvasSharedPtr mpOutputCanvas;
+
+ /// ptr back to owning view. needed for isOnView() method
+ View const* const mpParentView;
+
+public:
+ /** Create a new layer
+
+ @param pCanvas
+ Sprite canvas to create the layer on
+
+ @param rTransform
+ Initial overall canvas transformation
+
+ @param rLayerBounds
+ Initial layer bounds, in view coordinate system
+ */
+ SlideViewLayer( const cppcanvas::SpriteCanvasSharedPtr& pCanvas,
+ const basegfx::B2DHomMatrix& rTransform,
+ const basegfx::B2DRange& rLayerBounds,
+ const basegfx::B2DSize& rUserSize,
+ View const* const pParentView) :
+ maSpriteContainer(),
+ maLayerBounds(rLayerBounds),
+ maLayerBoundsPixel(),
+ maClip(),
+ maUserSize(rUserSize),
+ maTransformation(rTransform),
+ mpSpriteCanvas(pCanvas),
+ mpSprite(),
+ mpOutputCanvas(),
+ mpParentView(pParentView)
+ {
+ }
+
+ void updateView( const basegfx::B2DHomMatrix& rMatrix,
+ const basegfx::B2DSize& rUserSize )
+ {
+ maTransformation = rMatrix;
+ maUserSize = rUserSize;
+
+ // limit layer bounds to visible screen
+ maLayerBounds.intersect( basegfx::B2DRange(0.0,
+ 0.0,
+ maUserSize.getX(),
+ maUserSize.getY()) );
+
+ basegfx::B2IRange const& rNewLayerPixel(
+ getLayerBoundsPixel(maLayerBounds,
+ maTransformation) );
+ if( rNewLayerPixel != maLayerBoundsPixel )
+ {
+ // re-gen sprite with new size
+ mpOutputCanvas.reset();
+ mpSprite.reset();
+ }
+ }
+
+private:
+ // ViewLayer interface
+ // ----------------------------------------------
+
+ virtual cppcanvas::CustomSpriteSharedPtr createSprite(
+ const ::basegfx::B2DSize& rSpriteSizePixel,
+ double nPriority ) const
+ {
+ cppcanvas::CustomSpriteSharedPtr pSprite(
+ mpSpriteCanvas->createCustomSprite( rSpriteSizePixel ) );
+
+ maSpriteContainer.addSprite( pSprite,
+ nPriority );
+
+ return pSprite;
+ }
+
+ virtual void setPriority( const basegfx::B1DRange& rRange )
+ {
+ OSL_ENSURE( !rRange.isEmpty() &&
+ rRange.getMinimum() >= 1.0,
+ "SlideViewLayer::setPriority(): prio MUST be larger than 1.0 (because "
+ "the background layer already lies there)" );
+
+ maSpriteContainer.setLayerPriority( rRange );
+
+ if( mpSprite )
+ mpSprite->setPriority( rRange.getMinimum() );
+ }
+
+ virtual basegfx::B2DHomMatrix getTransformation() const
+ {
+ // Offset given transformation by left, top border of given
+ // range (after transformation through given transformation)
+ basegfx::B2DRectangle aTmpRect;
+ canvas::tools::calcTransformedRectBounds( aTmpRect,
+ maLayerBounds,
+ maTransformation );
+
+ basegfx::B2DHomMatrix aMatrix( maTransformation );
+
+ // Add translation according to the origin of aTmpRect. Ignore the
+ // translation when aTmpRect was not properly initialized.
+ if ( ! aTmpRect.isEmpty())
+ {
+ aMatrix.translate( -basegfx::fround(aTmpRect.getMinX()),
+ -basegfx::fround(aTmpRect.getMinY()) );
+ }
+
+ return aMatrix;
+ }
+
+ virtual basegfx::B2DHomMatrix getSpriteTransformation() const
+ {
+ return maTransformation;
+ }
+
+ virtual void clear() const
+ {
+ // keep layer clip
+ clearRect(getCanvas()->clone(),
+ maLayerBoundsPixel);
+ }
+
+ virtual void clearAll() const
+ {
+ ::cppcanvas::CanvasSharedPtr pCanvas( getCanvas()->clone() );
+
+ // clear layer clip, to clear whole area
+ pCanvas->setClip();
+
+ clearRect(pCanvas,
+ maLayerBoundsPixel);
+ }
+
+ virtual bool isOnView(boost::shared_ptr<View> const& rView) const
+ {
+ return rView.get() == mpParentView;
+ }
+
+ virtual cppcanvas::CanvasSharedPtr getCanvas() const
+ {
+ if( !mpOutputCanvas )
+ {
+ if( !mpSprite )
+ {
+ maLayerBoundsPixel = getLayerBoundsPixel(maLayerBounds,
+ maTransformation);
+
+ // HACK: ensure at least 1x1 pixel size. clients might
+ // need an actual canvas (e.g. for bound rect
+ // calculations) without rendering anything. Better
+ // solution: introduce something like a reference
+ // canvas for ViewLayers, which is always available.
+ if( maLayerBoundsPixel.isEmpty() )
+ maLayerBoundsPixel = basegfx::B2IRange(0,0,1,1);
+
+ const basegfx::B2I64Tuple& rSpriteSize(maLayerBoundsPixel.getRange());
+ mpSprite = mpSpriteCanvas->createCustomSprite(
+ basegfx::B2DVector(sal::static_int_cast<sal_Int32>(rSpriteSize.getX()),
+ sal::static_int_cast<sal_Int32>(rSpriteSize.getY())) );
+
+ mpSprite->setPriority(
+ maSpriteContainer.getLayerPriority().getMinimum() );
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ mpSprite->movePixel(
+ basegfx::B2DPoint(maLayerBoundsPixel.getMinimum()) +
+ basegfx::B2DPoint(10,10) );
+
+ mpSprite->setAlpha(0.5);
+#else
+ mpSprite->movePixel(
+ basegfx::B2DPoint(maLayerBoundsPixel.getMinimum()) );
+
+ mpSprite->setAlpha(1.0);
+#endif
+ mpSprite->show();
+ }
+
+ ENSURE_OR_THROW( mpSprite,
+ "SlideViewLayer::getCanvas(): no layer sprite" );
+
+ mpOutputCanvas = mpSprite->getContentCanvas();
+
+ ENSURE_OR_THROW( mpOutputCanvas,
+ "SlideViewLayer::getCanvas(): sprite doesn't yield a canvas" );
+
+ // new canvas retrieved - setup transformation and clip
+ mpOutputCanvas->setTransformation( getTransformation() );
+ mpOutputCanvas->setClip(
+ createClipPolygon( maClip,
+ mpOutputCanvas,
+ maUserSize ));
+ }
+
+ return mpOutputCanvas;
+ }
+
+ virtual void setClip( const basegfx::B2DPolyPolygon& rClip )
+ {
+ basegfx::B2DPolyPolygon aNewClip = prepareClip( rClip );
+
+ if( aNewClip != maClip )
+ {
+ maClip = aNewClip;
+
+ if(mpOutputCanvas )
+ mpOutputCanvas->setClip(
+ createClipPolygon( maClip,
+ mpOutputCanvas,
+ maUserSize ));
+ }
+ }
+
+ virtual bool resize( const ::basegfx::B2DRange& rArea )
+ {
+ const bool bRet( maLayerBounds != rArea );
+ maLayerBounds = rArea;
+ updateView( maTransformation,
+ maUserSize );
+
+ return bRet;
+ }
+};
+
+
+// ---------------------------------------------------------
+
+typedef cppu::WeakComponentImplHelper2<
+ ::com::sun::star::util::XModifyListener,
+ ::com::sun::star::awt::XPaintListener> SlideViewBase;
+
+/** SlideView class
+
+ This class implements the View interface, encapsulating
+ <em>one</em> view a slideshow is displayed on.
+ */
+class SlideView : private cppu::BaseMutex,
+ public SlideViewBase,
+ public UnoView
+{
+public:
+ SlideView( const uno::Reference<presentation::XSlideShowView>& xView,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer );
+ void updateCanvas();
+
+private:
+ // View:
+ virtual ViewLayerSharedPtr createViewLayer( const basegfx::B2DRange& rLayerBounds ) const;
+ virtual bool updateScreen() const;
+ virtual bool paintScreen() const;
+ virtual void setViewSize( const ::basegfx::B2DSize& );
+ virtual void setCursorShape( sal_Int16 nPointerShape );
+
+ // ViewLayer interface
+ virtual bool isOnView(boost::shared_ptr<View> const& rView) const;
+ virtual void clear() const;
+ virtual void clearAll() const;
+ virtual cppcanvas::CanvasSharedPtr getCanvas() const;
+ virtual cppcanvas::CustomSpriteSharedPtr createSprite( const ::basegfx::B2DSize& rSpriteSizePixel,
+ double nPriority ) const;
+ virtual void setPriority( const basegfx::B1DRange& rRange );
+ virtual ::basegfx::B2DHomMatrix getTransformation() const;
+ virtual basegfx::B2DHomMatrix getSpriteTransformation() const;
+ virtual void setClip( const ::basegfx::B2DPolyPolygon& rClip );
+ virtual bool resize( const ::basegfx::B2DRange& rArea );
+
+ // UnoView:
+ virtual void _dispose();
+ virtual uno::Reference<presentation::XSlideShowView> getUnoView()const;
+ virtual void setIsSoundEnabled (const bool bValue);
+ virtual bool isSoundEnabled (void) const;
+
+ // XEventListener:
+ virtual void SAL_CALL disposing( lang::EventObject const& evt )
+ throw (uno::RuntimeException);
+ // XModifyListener:
+ virtual void SAL_CALL modified( const lang::EventObject& aEvent )
+ throw (uno::RuntimeException);
+ // XPaintListener:
+ virtual void SAL_CALL windowPaint( const awt::PaintEvent& e )
+ throw (uno::RuntimeException);
+
+ // WeakComponentImplHelperBase:
+ virtual void SAL_CALL disposing();
+
+ void updateClip();
+
+private:
+ typedef std::vector< boost::weak_ptr<SlideViewLayer> > ViewLayerVector;
+
+ /// Prune viewlayers from deceased ones, optionally update them
+ void pruneLayers( bool bWithViewLayerUpdate=false ) const;
+
+ /** Max fill level of maViewLayers, before we try to prune it from
+ deceased layers
+ */
+ enum{ LAYER_ULLAGE=8 };
+
+ uno::Reference<presentation::XSlideShowView> mxView;
+ cppcanvas::SpriteCanvasSharedPtr mpCanvas;
+
+ EventMultiplexer& mrEventMultiplexer;
+ EventQueue& mrEventQueue;
+
+ mutable LayerSpriteContainer maSprites;
+ mutable ViewLayerVector maViewLayers;
+
+ basegfx::B2DPolyPolygon maClip;
+
+ basegfx::B2DHomMatrix maViewTransform;
+ basegfx::B2DSize maUserSize;
+ bool mbIsSoundEnabled;
+};
+
+
+SlideView::SlideView( const uno::Reference<presentation::XSlideShowView>& xView,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer ) :
+ SlideViewBase( m_aMutex ),
+ mxView( xView ),
+ mpCanvas(),
+ mrEventMultiplexer( rEventMultiplexer ),
+ mrEventQueue( rEventQueue ),
+ maSprites(),
+ maViewLayers(),
+ maClip(),
+ maViewTransform(),
+ maUserSize( 1.0, 1.0 ), // default size: one-by-one rectangle
+ mbIsSoundEnabled(true)
+{
+ // take care not constructing any UNO references to this _inside_
+ // ctor, shift that code to createSlideView()!
+ ENSURE_OR_THROW( mxView.is(),
+ "SlideView::SlideView(): Invalid view" );
+
+ mpCanvas = cppcanvas::VCLFactory::getInstance().createSpriteCanvas(
+ xView->getCanvas() );
+ ENSURE_OR_THROW( mpCanvas,
+ "Could not create cppcanvas" );
+
+ geometry::AffineMatrix2D aViewTransform(
+ xView->getTransformation() );
+
+ if( basegfx::fTools::equalZero(
+ basegfx::B2DVector(aViewTransform.m00,
+ aViewTransform.m10).getLength()) ||
+ basegfx::fTools::equalZero(
+ basegfx::B2DVector(aViewTransform.m01,
+ aViewTransform.m11).getLength()) )
+ {
+ OSL_ENSURE( false,
+ "SlideView::SlideView(): Singular matrix!" );
+
+ canvas::tools::setIdentityAffineMatrix2D(aViewTransform);
+ }
+
+ basegfx::unotools::homMatrixFromAffineMatrix(
+ maViewTransform, aViewTransform );
+
+ // once and forever: set fixed prio to this 'layer' (we're always
+ // the background layer)
+ maSprites.setLayerPriority( basegfx::B1DRange(0.0,1.0) );
+}
+
+void SlideView::disposing()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ maViewLayers.clear();
+ maSprites.clear();
+ mpCanvas.reset();
+
+ // additionally, also de-register from XSlideShowView
+ if (mxView.is())
+ {
+ mxView->removeTransformationChangedListener( this );
+ mxView->removePaintListener( this );
+ mxView.clear();
+ }
+}
+
+ViewLayerSharedPtr SlideView::createViewLayer( const basegfx::B2DRange& rLayerBounds ) const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ENSURE_OR_THROW( mpCanvas,
+ "SlideView::createViewLayer(): Disposed" );
+
+ const std::size_t nNumLayers( maViewLayers.size() );
+
+ // avoid filling up layer vector with lots of deceased layer weak
+ // ptrs
+ if( nNumLayers > LAYER_ULLAGE )
+ pruneLayers();
+
+ boost::shared_ptr<SlideViewLayer> pViewLayer( new SlideViewLayer(mpCanvas,
+ getTransformation(),
+ rLayerBounds,
+ maUserSize,
+ this) );
+ maViewLayers.push_back( pViewLayer );
+
+ return pViewLayer;
+}
+
+bool SlideView::updateScreen() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ENSURE_OR_RETURN_FALSE( mpCanvas.get(),
+ "SlideView::updateScreen(): Disposed" );
+
+ return mpCanvas->updateScreen( false );
+}
+
+bool SlideView::paintScreen() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ENSURE_OR_RETURN_FALSE( mpCanvas.get(),
+ "SlideView::paintScreen(): Disposed" );
+
+ return mpCanvas->updateScreen( true );
+}
+
+void SlideView::clear() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ OSL_ENSURE( mxView.is() && mpCanvas,
+ "SlideView::clear(): Disposed" );
+ if( !mxView.is() || !mpCanvas )
+ return;
+
+ // keep layer clip
+ clearRect(getCanvas()->clone(),
+ getLayerBoundsPixel(
+ basegfx::B2DRange(0,0,
+ maUserSize.getX(),
+ maUserSize.getY()),
+ getTransformation()));
+}
+
+void SlideView::clearAll() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ OSL_ENSURE( mxView.is() && mpCanvas,
+ "SlideView::clear(): Disposed" );
+ if( !mxView.is() || !mpCanvas )
+ return;
+
+ // clear whole view
+ mxView->clear();
+}
+
+void SlideView::setViewSize( const basegfx::B2DSize& rSize )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ maUserSize = rSize;
+ updateCanvas();
+}
+
+void SlideView::setCursorShape( sal_Int16 nPointerShape )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (mxView.is())
+ mxView->setMouseCursor( nPointerShape );
+}
+
+bool SlideView::isOnView(boost::shared_ptr<View> const& rView) const
+{
+ return rView.get() == this;
+}
+
+cppcanvas::CanvasSharedPtr SlideView::getCanvas() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ENSURE_OR_THROW( mpCanvas,
+ "SlideView::getCanvas(): Disposed" );
+
+ return mpCanvas;
+}
+
+cppcanvas::CustomSpriteSharedPtr SlideView::createSprite(
+ const basegfx::B2DSize& rSpriteSizePixel,
+ double nPriority ) const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ENSURE_OR_THROW( mpCanvas, "SlideView::createSprite(): Disposed" );
+
+ cppcanvas::CustomSpriteSharedPtr pSprite(
+ mpCanvas->createCustomSprite( rSpriteSizePixel ) );
+
+ maSprites.addSprite( pSprite,
+ nPriority );
+
+ return pSprite;
+}
+
+void SlideView::setPriority( const basegfx::B1DRange& /*rRange*/ )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ OSL_ENSURE( false,
+ "SlideView::setPriority() is a NOOP for slide view - "
+ "content will always be shown in the background" );
+}
+
+basegfx::B2DHomMatrix SlideView::getTransformation() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.scale( 1.0/maUserSize.getX(), 1.0/maUserSize.getY() );
+
+ return maViewTransform * aMatrix;
+}
+
+basegfx::B2DHomMatrix SlideView::getSpriteTransformation() const
+{
+ return getTransformation();
+}
+
+void SlideView::setClip( const basegfx::B2DPolyPolygon& rClip )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ basegfx::B2DPolyPolygon aNewClip = prepareClip( rClip );
+
+ if( aNewClip != maClip )
+ {
+ maClip = aNewClip;
+
+ updateClip();
+ }
+}
+
+bool SlideView::resize( const ::basegfx::B2DRange& /*rArea*/ )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ OSL_ENSURE( false,
+ "SlideView::resize(): ignored for the View, can't change size "
+ "effectively, anyway" );
+
+ return false;
+}
+
+uno::Reference<presentation::XSlideShowView> SlideView::getUnoView() const
+{
+ osl::MutexGuard aGuard( m_aMutex );
+ return mxView;
+}
+
+void SlideView::setIsSoundEnabled (const bool bValue)
+{
+ mbIsSoundEnabled = bValue;
+}
+
+bool SlideView::isSoundEnabled (void) const
+{
+ return mbIsSoundEnabled;
+}
+
+void SlideView::_dispose()
+{
+ dispose();
+}
+
+// XEventListener
+void SlideView::disposing( lang::EventObject const& evt )
+ throw (uno::RuntimeException)
+{
+ (void)evt;
+
+ // no deregistration necessary anymore, XView has left:
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (mxView.is())
+ {
+ OSL_ASSERT( evt.Source == mxView );
+ mxView.clear();
+ }
+
+ dispose();
+}
+
+// XModifyListener
+void SlideView::modified( const lang::EventObject& /*aEvent*/ )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ OSL_ENSURE( mxView.is(), "SlideView::modified(): "
+ "Disposed, but event received from XSlideShowView?!");
+
+ if( !mxView.is() )
+ return;
+
+ geometry::AffineMatrix2D aViewTransform(
+ mxView->getTransformation() );
+
+ if( basegfx::fTools::equalZero(
+ basegfx::B2DVector(aViewTransform.m00,
+ aViewTransform.m10).getLength()) ||
+ basegfx::fTools::equalZero(
+ basegfx::B2DVector(aViewTransform.m01,
+ aViewTransform.m11).getLength()) )
+ {
+ OSL_ENSURE( false,
+ "SlideView::modified(): Singular matrix!" );
+
+ canvas::tools::setIdentityAffineMatrix2D(aViewTransform);
+ }
+
+ // view transformation really changed?
+ basegfx::B2DHomMatrix aNewTransform;
+ basegfx::unotools::homMatrixFromAffineMatrix(
+ aNewTransform,
+ aViewTransform );
+
+ if( aNewTransform == maViewTransform )
+ return; // No change, nothing to do
+
+ maViewTransform = aNewTransform;
+
+ updateCanvas();
+
+ // notify view change. Don't call EventMultiplexer directly, this
+ // might not be the main thread!
+ mrEventQueue.addEvent(
+ makeEvent( boost::bind( (bool (EventMultiplexer::*)(
+ const uno::Reference<presentation::XSlideShowView>&))
+ &EventMultiplexer::notifyViewChanged,
+ boost::ref(mrEventMultiplexer), mxView ),
+ "EventMultiplexer::notifyViewChanged"));
+}
+
+// XPaintListener
+void SlideView::windowPaint( const awt::PaintEvent& /*e*/ )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ OSL_ENSURE( mxView.is() && mpCanvas, "Disposed, but event received?!" );
+
+ // notify view clobbering. Don't call EventMultiplexer directly,
+ // this might not be the main thread!
+ mrEventQueue.addEvent(
+ makeEvent( boost::bind( &EventMultiplexer::notifyViewClobbered,
+ boost::ref(mrEventMultiplexer), mxView ),
+ "EventMultiplexer::notifyViewClobbered") );
+}
+
+void SlideView::updateCanvas()
+{
+ OSL_ENSURE( mpCanvas,
+ "SlideView::updateCanvasTransform(): Disposed" );
+
+ if( !mpCanvas || !mxView.is())
+ return;
+
+ mpCanvas->clear(); // this is unnecessary, strictly speaking. but
+ // it makes the SlideView behave exactly like a
+ // sprite-based SlideViewLayer, because those
+ // are created from scratch after a resize
+ clearAll();
+ mpCanvas->setTransformation( getTransformation() );
+ mpCanvas->setClip(
+ createClipPolygon( maClip,
+ mpCanvas,
+ maUserSize ));
+
+ // forward update to viewlayers
+ pruneLayers( true );
+}
+
+void SlideView::updateClip()
+{
+ OSL_ENSURE( mpCanvas,
+ "SlideView::updateClip(): Disposed" );
+
+ if( !mpCanvas )
+ return;
+
+ mpCanvas->setClip(
+ createClipPolygon( maClip,
+ mpCanvas,
+ maUserSize ));
+
+ pruneLayers( false );
+}
+
+void SlideView::pruneLayers( bool bWithViewLayerUpdate ) const
+{
+ ViewLayerVector aValidLayers;
+
+ const basegfx::B2DHomMatrix& rCurrTransform(
+ getTransformation() );
+
+ // check all layers for validity, and retain only the live ones
+ ViewLayerVector::const_iterator aCurr( maViewLayers.begin() );
+ const ViewLayerVector::const_iterator aEnd( maViewLayers.end() );
+ while( aCurr != aEnd )
+ {
+ boost::shared_ptr< SlideViewLayer > pCurrLayer( aCurr->lock() );
+
+ if( pCurrLayer )
+ {
+ aValidLayers.push_back( pCurrLayer );
+
+ if( bWithViewLayerUpdate )
+ pCurrLayer->updateView( rCurrTransform,
+ maUserSize );
+ }
+
+ ++aCurr;
+ }
+
+ // replace layer list with pruned one
+ maViewLayers.swap( aValidLayers );
+}
+
+} // anonymous namespace
+
+UnoViewSharedPtr createSlideView( uno::Reference< presentation::XSlideShowView> const& xView,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer )
+{
+ boost::shared_ptr<SlideView> const that(
+ comphelper::make_shared_from_UNO(
+ new SlideView(xView,
+ rEventQueue,
+ rEventMultiplexer)));
+
+ // register listeners with XSlideShowView
+ xView->addTransformationChangedListener( that.get() );
+ xView->addPaintListener( that.get() );
+
+ // set new transformation
+ that->updateCanvas();
+
+ return that;
+}
+
+} // namespace internal
+} // namespace slideshow
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/smilfunctionparser.cxx b/slideshow/source/engine/smilfunctionparser.cxx
new file mode 100644
index 000000000000..69a61c50ecf4
--- /dev/null
+++ b/slideshow/source/engine/smilfunctionparser.cxx
@@ -0,0 +1,641 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <rtl/math.hxx>
+
+#include <smilfunctionparser.hxx>
+#include <expressionnodefactory.hxx>
+
+#include <rtl/ustring.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+// Makes parser a static resource,
+// we're synchronized externally.
+// But watch out, the parser might have
+// state not visible to this code!
+#define BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
+#if defined(VERBOSE) && defined(DBG_UTIL)
+#include <typeinfo>
+#define BOOST_SPIRIT_DEBUG
+#endif
+#include <boost/spirit/include/classic_core.hpp>
+
+#if OSL_DEBUG_LEVEL > 0
+#include <iostream>
+#endif
+#include <functional>
+#include <algorithm>
+#include <stack>
+
+
+
+/* Implementation of SmilFunctionParser class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ namespace
+ {
+ typedef const sal_Char* StringIteratorT;
+
+ struct ParserContext
+ {
+ typedef ::std::stack< ExpressionNodeSharedPtr > OperandStack;
+
+ // stores a stack of not-yet-evaluated operands. This is used
+ // by the operators (i.e. '+', '*', 'sin' etc.) to pop their
+ // arguments from. If all arguments to an operator are constant,
+ // the operator pushes a precalculated result on the stack, and
+ // a composite ExpressionNode otherwise.
+ OperandStack maOperandStack;
+
+ // bounds of the shape this expression is associated with
+ ::basegfx::B2DRectangle maShapeBounds;
+
+ // when true, enable usage of time-dependent variable '$'
+ // in expressions
+ bool mbParseAnimationFunction;
+ };
+
+ typedef ::boost::shared_ptr< ParserContext > ParserContextSharedPtr;
+
+
+ template< typename Generator > class ShapeBoundsFunctor
+ {
+ public:
+ ShapeBoundsFunctor( Generator aGenerator,
+ const ParserContextSharedPtr& rContext ) :
+ maGenerator( aGenerator ),
+ mpContext( rContext )
+ {
+ ENSURE_OR_THROW( mpContext,
+ "ShapeBoundsFunctor::ShapeBoundsFunctor(): Invalid context" );
+ }
+
+ void operator()( StringIteratorT, StringIteratorT ) const
+ {
+ mpContext->maOperandStack.push(
+ ExpressionNodeFactory::createConstantValueExpression(
+ maGenerator( mpContext->maShapeBounds ) ) );
+ }
+
+ private:
+ Generator maGenerator;
+ ParserContextSharedPtr mpContext;
+ };
+
+ template< typename Generator > ShapeBoundsFunctor< Generator >
+ makeShapeBoundsFunctor( const Generator& rGenerator,
+ const ParserContextSharedPtr& rContext )
+ {
+ return ShapeBoundsFunctor<Generator>(rGenerator, rContext);
+ }
+
+ /** Generate apriori constant value
+ */
+ class ConstantFunctor
+ {
+ public:
+ ConstantFunctor( double rValue,
+ const ParserContextSharedPtr& rContext ) :
+ mnValue( rValue ),
+ mpContext( rContext )
+ {
+ ENSURE_OR_THROW( mpContext,
+ "ConstantFunctor::ConstantFunctor(): Invalid context" );
+ }
+
+ void operator()( StringIteratorT, StringIteratorT ) const
+ {
+ mpContext->maOperandStack.push(
+ ExpressionNodeFactory::createConstantValueExpression( mnValue ) );
+ }
+
+ private:
+ const double mnValue;
+ ParserContextSharedPtr mpContext;
+ };
+
+ /** Generate parse-dependent-but-then-constant value
+ */
+ class DoubleConstantFunctor
+ {
+ public:
+ DoubleConstantFunctor( const ParserContextSharedPtr& rContext ) :
+ mpContext( rContext )
+ {
+ ENSURE_OR_THROW( mpContext,
+ "DoubleConstantFunctor::DoubleConstantFunctor(): Invalid context" );
+ }
+
+ void operator()( double n ) const
+ {
+ // push constant value expression to the stack
+ mpContext->maOperandStack.push(
+ ExpressionNodeFactory::createConstantValueExpression( n ) );
+ }
+
+ private:
+ ParserContextSharedPtr mpContext;
+ };
+
+ /** Generate special t value expression node
+ */
+ class ValueTFunctor
+ {
+ public:
+ ValueTFunctor( const ParserContextSharedPtr& rContext ) :
+ mpContext( rContext )
+ {
+ ENSURE_OR_THROW( mpContext,
+ "ValueTFunctor::ValueTFunctor(): Invalid context" );
+ }
+
+ void operator()( StringIteratorT, StringIteratorT ) const
+ {
+ if( !mpContext->mbParseAnimationFunction )
+ {
+ OSL_ENSURE( false,
+ "ValueTFunctor::operator(): variable encountered, but we're not parsing a function here" );
+ throw ParseError();
+ }
+
+ // push special t value expression to the stack
+ mpContext->maOperandStack.push(
+ ExpressionNodeFactory::createValueTExpression() );
+ }
+
+ private:
+ ParserContextSharedPtr mpContext;
+ };
+
+ template< typename Functor > class UnaryFunctionFunctor
+ {
+ private:
+ /** ExpressionNode implementation for unary
+ function over one ExpressionNode
+ */
+ class UnaryFunctionExpression : public ExpressionNode
+ {
+ public:
+ UnaryFunctionExpression( const Functor& rFunctor,
+ const ExpressionNodeSharedPtr& rArg ) :
+ maFunctor( rFunctor ),
+ mpArg( rArg )
+ {
+ }
+
+ virtual double operator()( double t ) const
+ {
+ return maFunctor( (*mpArg)(t) );
+ }
+
+ virtual bool isConstant() const
+ {
+ return mpArg->isConstant();
+ }
+
+ private:
+ Functor maFunctor;
+ ExpressionNodeSharedPtr mpArg;
+ };
+
+ public:
+ UnaryFunctionFunctor( const Functor& rFunctor,
+ const ParserContextSharedPtr& rContext ) :
+ maFunctor( rFunctor ),
+ mpContext( rContext )
+ {
+ ENSURE_OR_THROW( mpContext,
+ "UnaryFunctionFunctor::UnaryFunctionFunctor(): Invalid context" );
+ }
+
+ void operator()( StringIteratorT, StringIteratorT ) const
+ {
+ ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
+
+ if( rNodeStack.size() < 1 )
+ throw ParseError( "Not enough arguments for unary operator" );
+
+ // retrieve arguments
+ ExpressionNodeSharedPtr pArg( rNodeStack.top() );
+ rNodeStack.pop();
+
+ // check for constness
+ if( pArg->isConstant() )
+ {
+ rNodeStack.push(
+ ExpressionNodeFactory::createConstantValueExpression(
+ maFunctor( (*pArg)(0.0) ) ) );
+ }
+ else
+ {
+ // push complex node, that calcs the value on demand
+ rNodeStack.push(
+ ExpressionNodeSharedPtr(
+ new UnaryFunctionExpression(
+ maFunctor,
+ pArg ) ) );
+ }
+ }
+
+ private:
+ Functor maFunctor;
+ ParserContextSharedPtr mpContext;
+ };
+
+ // TODO(Q2): Refactor makeUnaryFunctionFunctor,
+ // makeBinaryFunctionFunctor and the whole
+ // ExpressionNodeFactory, to use a generic
+ // makeFunctionFunctor template, which is overloaded for
+ // unary, binary, ternary, etc. function pointers.
+ template< typename Functor > UnaryFunctionFunctor<Functor>
+ makeUnaryFunctionFunctor( const Functor& rFunctor,
+ const ParserContextSharedPtr& rContext )
+ {
+ return UnaryFunctionFunctor<Functor>( rFunctor, rContext );
+ }
+
+ // MSVC has problems instantiating above template function with plain function
+ // pointers (doesn't like the const reference there). Thus, provide it with
+ // a dedicated overload here.
+ UnaryFunctionFunctor< double (*)(double) >
+ makeUnaryFunctionFunctor( double (*pFunc)(double),
+ const ParserContextSharedPtr& rContext )
+ {
+ return UnaryFunctionFunctor< double (*)(double) >( pFunc, rContext );
+ }
+
+ /** Implements a binary function over two ExpressionNodes
+
+ @tpl Generator
+ Generator functor, to generate an ExpressionNode of
+ appropriate type
+
+ */
+ template< class Generator > class BinaryFunctionFunctor
+ {
+ public:
+ BinaryFunctionFunctor( const Generator& rGenerator,
+ const ParserContextSharedPtr& rContext ) :
+ maGenerator( rGenerator ),
+ mpContext( rContext )
+ {
+ ENSURE_OR_THROW( mpContext,
+ "BinaryFunctionFunctor::BinaryFunctionFunctor(): Invalid context" );
+ }
+
+ void operator()( StringIteratorT, StringIteratorT ) const
+ {
+ ParserContext::OperandStack& rNodeStack( mpContext->maOperandStack );
+
+ if( rNodeStack.size() < 2 )
+ throw ParseError( "Not enough arguments for binary operator" );
+
+ // retrieve arguments
+ ExpressionNodeSharedPtr pSecondArg( rNodeStack.top() );
+ rNodeStack.pop();
+ ExpressionNodeSharedPtr pFirstArg( rNodeStack.top() );
+ rNodeStack.pop();
+
+ // create combined ExpressionNode
+ ExpressionNodeSharedPtr pNode( maGenerator( pFirstArg,
+ pSecondArg ) );
+ // check for constness
+ if( pFirstArg->isConstant() &&
+ pSecondArg->isConstant() )
+ {
+ // call the operator() at pNode, store result
+ // in constant value ExpressionNode.
+ rNodeStack.push(
+ ExpressionNodeFactory::createConstantValueExpression(
+ (*pNode)( 0.0 ) ) );
+ }
+ else
+ {
+ // push complex node, that calcs the value on demand
+ rNodeStack.push( pNode );
+ }
+ }
+
+ private:
+ Generator maGenerator;
+ ParserContextSharedPtr mpContext;
+ };
+
+ template< typename Generator > BinaryFunctionFunctor<Generator>
+ makeBinaryFunctionFunctor( const Generator& rGenerator,
+ const ParserContextSharedPtr& rContext )
+ {
+ return BinaryFunctionFunctor<Generator>( rGenerator, rContext );
+ }
+
+
+ // Workaround for MSVC compiler anomaly (stack trashing)
+ //
+ // The default ureal_parser_policies implementation of parse_exp
+ // triggers a really weird error in MSVC7 (Version 13.00.9466), in
+ // that the real_parser_impl::parse_main() call of parse_exp()
+ // overwrites the frame pointer _on the stack_ (EBP of the calling
+ // function gets overwritten while lying on the stack).
+ //
+ // For the time being, our parser thus can only read the 1.0E10
+ // notation, not the 1.0e10 one.
+ //
+ // TODO(F1): Also handle the 1.0e10 case here.
+ template< typename T > struct custom_real_parser_policies : public ::boost::spirit::ureal_parser_policies<T>
+ {
+ template< typename ScannerT >
+ static typename ::boost::spirit::parser_result< ::boost::spirit::chlit<>, ScannerT >::type
+ parse_exp(ScannerT& scan)
+ {
+ // as_lower_d somehow breaks MSVC7
+ return ::boost::spirit::ch_p('E').parse(scan);
+ }
+ };
+
+ /* This class implements the following grammar (more or
+ less literally written down below, only slightly
+ obfuscated by the parser actions):
+
+ identifier = '$'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
+
+ function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
+
+ basic_expression =
+ number |
+ identifier |
+ function '(' additive_expression ')' |
+ '(' additive_expression ')'
+
+ unary_expression =
+ '-' basic_expression |
+ basic_expression
+
+ multiplicative_expression =
+ unary_expression ( ( '*' unary_expression )* |
+ ( '/' unary_expression )* )
+
+ additive_expression =
+ multiplicative_expression ( ( '+' multiplicative_expression )* |
+ ( '-' multiplicative_expression )* )
+
+ */
+ class ExpressionGrammar : public ::boost::spirit::grammar< ExpressionGrammar >
+ {
+ public:
+ /** Create an arithmetic expression grammar
+
+ @param rParserContext
+ Contains context info for the parser
+ */
+ ExpressionGrammar( const ParserContextSharedPtr& rParserContext ) :
+ mpParserContext( rParserContext )
+ {
+ }
+
+ template< typename ScannerT > class definition
+ {
+ public:
+ // grammar definition
+ definition( const ExpressionGrammar& self )
+ {
+ using ::boost::spirit::str_p;
+ using ::boost::spirit::real_parser;
+
+ identifier =
+ str_p( "$" )[ ValueTFunctor( self.getContext()) ]
+ | str_p( "pi" )[ ConstantFunctor(M_PI, self.getContext()) ]
+ | str_p( "e" )[ ConstantFunctor(M_E, self.getContext()) ]
+ | str_p( "x" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getCenterX),self.getContext()) ]
+ | str_p( "y" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getCenterY),self.getContext()) ]
+ | str_p( "width" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getWidth), self.getContext()) ]
+ | str_p( "height" )[ makeShapeBoundsFunctor(::std::mem_fun_ref(&::basegfx::B2DRange::getHeight), self.getContext()) ]
+ ;
+
+ unaryFunction =
+ (str_p( "abs" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&fabs, self.getContext()) ]
+ | (str_p( "sqrt" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&sqrt, self.getContext()) ]
+ | (str_p( "sin" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&sin, self.getContext()) ]
+ | (str_p( "cos" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&cos, self.getContext()) ]
+ | (str_p( "tan" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&tan, self.getContext()) ]
+ | (str_p( "atan" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&atan, self.getContext()) ]
+ | (str_p( "acos" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&acos, self.getContext()) ]
+ | (str_p( "asin" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&asin, self.getContext()) ]
+ | (str_p( "exp" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&exp, self.getContext()) ]
+ | (str_p( "log" ) >> '(' >> additiveExpression >> ')' )[ makeUnaryFunctionFunctor(&log, self.getContext()) ]
+ ;
+
+ binaryFunction =
+ (str_p( "min" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMinExpression, self.getContext()) ]
+ | (str_p( "max" ) >> '(' >> additiveExpression >> ',' >> additiveExpression >> ')' )[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMaxExpression, self.getContext()) ]
+ ;
+
+ basicExpression =
+ real_parser<double, custom_real_parser_policies<double> >()[ DoubleConstantFunctor(self.getContext()) ]
+ | identifier
+ | unaryFunction
+ | binaryFunction
+ | '(' >> additiveExpression >> ')'
+ ;
+
+ unaryExpression =
+ ('-' >> basicExpression)[ makeUnaryFunctionFunctor(::std::negate<double>(), self.getContext()) ]
+ | basicExpression
+ ;
+
+ multiplicativeExpression =
+ unaryExpression
+ >> *( ('*' >> unaryExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMultipliesExpression, self.getContext()) ]
+ | ('/' >> unaryExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createDividesExpression, self.getContext()) ]
+ )
+ ;
+
+ additiveExpression =
+ multiplicativeExpression
+ >> *( ('+' >> multiplicativeExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createPlusExpression, self.getContext()) ]
+ | ('-' >> multiplicativeExpression)[ makeBinaryFunctionFunctor(&ExpressionNodeFactory::createMinusExpression, self.getContext()) ]
+ )
+ ;
+
+ BOOST_SPIRIT_DEBUG_RULE(additiveExpression);
+ BOOST_SPIRIT_DEBUG_RULE(multiplicativeExpression);
+ BOOST_SPIRIT_DEBUG_RULE(unaryExpression);
+ BOOST_SPIRIT_DEBUG_RULE(basicExpression);
+ BOOST_SPIRIT_DEBUG_RULE(unaryFunction);
+ BOOST_SPIRIT_DEBUG_RULE(binaryFunction);
+ BOOST_SPIRIT_DEBUG_RULE(identifier);
+ }
+
+ const ::boost::spirit::rule< ScannerT >& start() const
+ {
+ return additiveExpression;
+ }
+
+ private:
+ // the constituents of the Spirit arithmetic expression grammar.
+ // For the sake of readability, without 'ma' prefix.
+ ::boost::spirit::rule< ScannerT > additiveExpression;
+ ::boost::spirit::rule< ScannerT > multiplicativeExpression;
+ ::boost::spirit::rule< ScannerT > unaryExpression;
+ ::boost::spirit::rule< ScannerT > basicExpression;
+ ::boost::spirit::rule< ScannerT > unaryFunction;
+ ::boost::spirit::rule< ScannerT > binaryFunction;
+ ::boost::spirit::rule< ScannerT > identifier;
+ };
+
+ const ParserContextSharedPtr& getContext() const
+ {
+ return mpParserContext;
+ }
+
+ private:
+ ParserContextSharedPtr mpParserContext; // might get modified during parsing
+ };
+
+#ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
+ const ParserContextSharedPtr& getParserContext()
+ {
+ static ParserContextSharedPtr lcl_parserContext( new ParserContext() );
+
+ // clear node stack (since we reuse the static object, that's
+ // the whole point here)
+ while( !lcl_parserContext->maOperandStack.empty() )
+ lcl_parserContext->maOperandStack.pop();
+
+ return lcl_parserContext;
+ }
+#endif
+ }
+
+ ExpressionNodeSharedPtr SmilFunctionParser::parseSmilValue( const ::rtl::OUString& rSmilValue,
+ const ::basegfx::B2DRectangle& rRelativeShapeBounds )
+ {
+ // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
+ // gives better conversion robustness here (we might want to map space
+ // etc. to ASCII space here)
+ const ::rtl::OString& rAsciiSmilValue(
+ rtl::OUStringToOString( rSmilValue, RTL_TEXTENCODING_ASCII_US ) );
+
+ StringIteratorT aStart( rAsciiSmilValue.getStr() );
+ StringIteratorT aEnd( rAsciiSmilValue.getStr()+rAsciiSmilValue.getLength() );
+
+ ParserContextSharedPtr pContext;
+
+#ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
+ // static parser context, because the actual
+ // Spirit parser is also a static object
+ pContext = getParserContext();
+#else
+ pContext.reset( new ParserContext() );
+#endif
+
+ pContext->maShapeBounds = rRelativeShapeBounds;
+ pContext->mbParseAnimationFunction = false; // parse with '$' disabled
+
+
+ ExpressionGrammar aExpressionGrammer( pContext );
+ const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
+ ::boost::spirit::parse( aStart,
+ aEnd,
+ aExpressionGrammer,
+ ::boost::spirit::space_p ) );
+ OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync
+
+ // input fully congested by the parser?
+ if( !aParseInfo.full )
+ throw ParseError( "SmilFunctionParser::parseSmilValue(): string not fully parseable" );
+
+ // parser's state stack now must contain exactly _one_ ExpressionNode,
+ // which represents our formula.
+ if( pContext->maOperandStack.size() != 1 )
+ throw ParseError( "SmilFunctionParser::parseSmilValue(): incomplete or empty expression" );
+
+ return pContext->maOperandStack.top();
+ }
+
+ ExpressionNodeSharedPtr SmilFunctionParser::parseSmilFunction( const ::rtl::OUString& rSmilFunction,
+ const ::basegfx::B2DRectangle& rRelativeShapeBounds )
+ {
+ // TODO(Q1): Check if a combination of the RTL_UNICODETOTEXT_FLAGS_*
+ // gives better conversion robustness here (we might want to map space
+ // etc. to ASCII space here)
+ const ::rtl::OString& rAsciiSmilFunction(
+ rtl::OUStringToOString( rSmilFunction, RTL_TEXTENCODING_ASCII_US ) );
+
+ StringIteratorT aStart( rAsciiSmilFunction.getStr() );
+ StringIteratorT aEnd( rAsciiSmilFunction.getStr()+rAsciiSmilFunction.getLength() );
+
+ ParserContextSharedPtr pContext;
+
+#ifdef BOOST_SPIRIT_SINGLE_GRAMMAR_INSTANCE
+ // static parser context, because the actual
+ // Spirit parser is also a static object
+ pContext = getParserContext();
+#else
+ pContext.reset( new ParserContext() );
+#endif
+
+ pContext->maShapeBounds = rRelativeShapeBounds;
+ pContext->mbParseAnimationFunction = true; // parse with '$' enabled
+
+
+ ExpressionGrammar aExpressionGrammer( pContext );
+ const ::boost::spirit::parse_info<StringIteratorT> aParseInfo(
+ ::boost::spirit::parse( aStart,
+ aEnd,
+ aExpressionGrammer >> ::boost::spirit::end_p,
+ ::boost::spirit::space_p ) );
+ OSL_DEBUG_ONLY(::std::cout.flush()); // needed to keep stdout and cout in sync
+
+ // input fully congested by the parser?
+ if( !aParseInfo.full )
+ throw ParseError( "SmilFunctionParser::parseSmilFunction(): string not fully parseable" );
+
+ // parser's state stack now must contain exactly _one_ ExpressionNode,
+ // which represents our formula.
+ if( pContext->maOperandStack.size() != 1 )
+ throw ParseError( "SmilFunctionParser::parseSmilFunction(): incomplete or empty expression" );
+
+ return pContext->maOperandStack.top();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/soundplayer.cxx b/slideshow/source/engine/soundplayer.cxx
new file mode 100644
index 000000000000..07b5c57554da
--- /dev/null
+++ b/slideshow/source/engine/soundplayer.cxx
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/verbosetrace.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/lang/XComponent.hdl>
+
+#include <tools/urlobj.hxx>
+
+#include <avmedia/mediawindow.hxx>
+
+#include "soundplayer.hxx"
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ // TODO(Q3): Move the whole SoundPlayer class to avmedia.
+
+ boost::shared_ptr<SoundPlayer> SoundPlayer::create(
+ EventMultiplexer & rEventMultiplexer,
+ const ::rtl::OUString& rSoundURL,
+ const uno::Reference< uno::XComponentContext>& rComponentContext )
+ {
+ boost::shared_ptr<SoundPlayer> pPlayer(
+ new SoundPlayer( rEventMultiplexer,
+ rSoundURL,
+ rComponentContext ) );
+ rEventMultiplexer.addPauseHandler( pPlayer );
+ pPlayer->mThis = pPlayer;
+ return pPlayer;
+ }
+
+ bool SoundPlayer::handlePause( bool bPauseShow )
+ {
+ return bPauseShow ? stopPlayback() : startPlayback();
+ }
+
+ void SoundPlayer::dispose()
+ {
+ if( mThis )
+ {
+ mrEventMultiplexer.removePauseHandler( mThis );
+ mThis.reset();
+ }
+
+ if( mxPlayer.is() )
+ {
+ mxPlayer->stop();
+ uno::Reference<lang::XComponent> xComponent(
+ mxPlayer, uno::UNO_QUERY );
+ if( xComponent.is() )
+ xComponent->dispose();
+ mxPlayer.clear();
+ }
+ }
+
+ SoundPlayer::SoundPlayer(
+ EventMultiplexer & rEventMultiplexer,
+ const ::rtl::OUString& rSoundURL,
+ const uno::Reference< uno::XComponentContext>& rComponentContext )
+ : mrEventMultiplexer(rEventMultiplexer),
+ mThis(),
+ mxPlayer()
+ {
+ ENSURE_OR_THROW( rComponentContext.is(),
+ "SoundPlayer::SoundPlayer(): Invalid component context" );
+
+ try
+ {
+ const INetURLObject aURL( rSoundURL );
+ mxPlayer.set( avmedia::MediaWindow::createPlayer(
+ aURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) ),
+ uno::UNO_QUERY);
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ if( !mxPlayer.is() )
+ throw lang::NoSupportException(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "No sound support for ") ) + rSoundURL,
+ uno::Reference<uno::XInterface>() );
+ }
+
+ SoundPlayer::~SoundPlayer()
+ {
+ try
+ {
+ dispose();
+ }
+ catch (uno::Exception &) {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ }
+
+ double SoundPlayer::getDuration() const
+ {
+ if( !mxPlayer.is() )
+ return 0.0;
+
+ const double nDuration( mxPlayer->getDuration() );
+ if( mxPlayer->isPlaying() )
+ return ::std::max( 0.0,
+ nDuration - mxPlayer->getMediaTime() );
+ else
+ return nDuration;
+ }
+
+ bool SoundPlayer::startPlayback()
+ {
+ if( !mxPlayer.is() )
+ return false;
+
+ if( mxPlayer->isPlaying() )
+ mxPlayer->stop();
+
+ mxPlayer->start();
+ return true;
+ }
+
+ bool SoundPlayer::stopPlayback()
+ {
+ if( mxPlayer.is() )
+ mxPlayer->stop();
+
+ return true;
+ }
+
+ void SoundPlayer::setPlaybackLoop( bool bLoop )
+ {
+ if( mxPlayer.is() )
+ mxPlayer->setPlaybackLoop( bLoop );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/sp_debug.cxx b/slideshow/source/engine/sp_debug.cxx
new file mode 100644
index 000000000000..25c5b2cff8a8
--- /dev/null
+++ b/slideshow/source/engine/sp_debug.cxx
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+//
+// sp_collector.cpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_mutex.hpp>
+#include <cstdlib>
+#include <map>
+#include <deque>
+#include <iostream>
+
+typedef std::map< void const *, std::pair<void *, size_t> > map_type;
+
+static map_type & get_map()
+{
+ static map_type m;
+ return m;
+}
+
+typedef boost::detail::lightweight_mutex mutex_type;
+
+static mutex_type & get_mutex()
+{
+ static mutex_type m;
+ return m;
+}
+
+static void * init_mutex_before_main = &get_mutex();
+
+namespace
+{
+ class X;
+
+ struct count_layout
+ {
+ boost::detail::sp_counted_base * pi;
+ int id;
+ };
+
+ struct shared_ptr_layout
+ {
+ X * px;
+ count_layout pn;
+ };
+}
+
+// assume 4 byte alignment for pointers when scanning
+size_t const pointer_align = 4;
+
+typedef std::map<void const *, long> map2_type;
+
+static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2)
+{
+ unsigned char const * p = static_cast<unsigned char const *>(area);
+
+ for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
+ {
+ shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
+
+ if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0)
+ {
+ ++m2[q->pn.pi];
+ }
+ }
+}
+
+typedef std::deque<void const *> open_type;
+
+static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open)
+{
+ unsigned char const * p = static_cast<unsigned char const *>(area);
+
+ for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
+ {
+ shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
+
+ if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0)
+ {
+ open.push_back(q->pn.pi);
+ m2.erase(q->pn.pi);
+ }
+ }
+}
+
+static void find_unreachable_objects_impl(map_type const & m, map2_type & m2)
+{
+ // scan objects for shared_ptr members, compute internal counts
+
+ {
+ std::cout << "... " << m.size() << " objects in m.\n";
+
+ for(map_type::const_iterator i = m.begin(); i != m.end(); ++i)
+ {
+ BOOST_ASSERT(static_cast<boost::detail::sp_counted_base const *>(i->first)->use_count() != 0); // there should be no inactive counts in the map
+
+ scan_and_count(i->second.first, i->second.second, m, m2);
+ }
+
+ std::cout << "... " << m2.size() << " objects in m2.\n";
+ }
+
+ // mark reachable objects
+
+ {
+ open_type open;
+
+ for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i)
+ {
+ boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
+ if(p->use_count() != i->second) open.push_back(p);
+ }
+
+ std::cout << "... " << m2.size() << " objects in open.\n";
+
+ for(open_type::iterator j = open.begin(); j != open.end(); ++j)
+ {
+ m2.erase(*j);
+ }
+
+ while(!open.empty())
+ {
+ void const * p = open.front();
+ open.pop_front();
+
+ map_type::const_iterator i = m.find(p);
+ BOOST_ASSERT(i != m.end());
+
+ scan_and_mark(i->second.first, i->second.second, m2, open);
+ }
+ }
+
+ // m2 now contains the unreachable objects
+}
+
+std::size_t find_unreachable_objects(bool report)
+{
+ map2_type m2;
+
+#ifdef BOOST_HAS_THREADS
+
+ // This will work without the #ifdef, but some compilers warn
+ // that lock is not referenced
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ map_type const & m = get_map();
+
+ find_unreachable_objects_impl(m, m2);
+
+ if(report)
+ {
+ for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
+ {
+ map_type::const_iterator i = m.find(j->first);
+ BOOST_ASSERT(i != m.end());
+ std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n";
+ }
+ }
+
+ return m2.size();
+}
+
+typedef std::deque< boost::shared_ptr<X> > free_list_type;
+
+static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free)
+{
+ unsigned char * p = static_cast<unsigned char *>(area);
+
+ for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
+ {
+ shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(p);
+
+ if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0)
+ {
+ boost::shared_ptr<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p);
+ free.push_back(*ppx);
+ ppx->reset();
+ }
+ }
+}
+
+void free_unreachable_objects()
+{
+ free_list_type free;
+
+ {
+ map2_type m2;
+
+#ifdef BOOST_HAS_THREADS
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ map_type const & m = get_map();
+
+ find_unreachable_objects_impl(m, m2);
+
+ for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
+ {
+ map_type::const_iterator i = m.find(j->first);
+ BOOST_ASSERT(i != m.end());
+ scan_and_free(i->second.first, i->second.second, m2, free);
+ }
+ }
+
+ std::cout << "... about to free " << free.size() << " objects.\n";
+}
+
+// debug hooks
+
+namespace boost
+{
+
+void sp_scalar_constructor_hook(void *)
+{
+}
+
+void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn)
+{
+#ifdef BOOST_HAS_THREADS
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ get_map()[pn] = std::make_pair(px, size);
+}
+
+void sp_scalar_destructor_hook(void *)
+{
+}
+
+void sp_scalar_destructor_hook(void *, std::size_t, void * pn)
+{
+#ifdef BOOST_HAS_THREADS
+
+ mutex_type::scoped_lock lock(get_mutex());
+
+#endif
+
+ get_map().erase(pn);
+}
+
+void sp_array_constructor_hook(void *)
+{
+}
+
+void sp_array_destructor_hook(void *)
+{
+}
+
+} // namespace boost
+
+#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/tools.cxx b/slideshow/source/engine/tools.cxx
new file mode 100644
index 000000000000..9a74e4114206
--- /dev/null
+++ b/slideshow/source/engine/tools.cxx
@@ -0,0 +1,856 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/canvastools.hxx>
+
+#include <math.h>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/animations/ValuePair.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tools/lerp.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include "unoview.hxx"
+#include "smilfunctionparser.hxx"
+#include "tools.hxx"
+
+#include <limits>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ namespace
+ {
+ class NamedValueStringComparator
+ {
+ public:
+ NamedValueStringComparator( const ::rtl::OUString& rSearchString ) :
+ mrSearchString( rSearchString )
+ {
+ }
+
+ bool operator()( const beans::NamedValue& rValue )
+ {
+ return rValue.Name == mrSearchString;
+ }
+
+ private:
+ const ::rtl::OUString& mrSearchString;
+ };
+
+ class NamedValueComparator
+ {
+ public:
+ NamedValueComparator( const beans::NamedValue& rKey ) :
+ mrKey( rKey )
+ {
+ }
+
+ bool operator()( const beans::NamedValue& rValue )
+ {
+ return rValue.Name == mrKey.Name && rValue.Value == mrKey.Value;
+ }
+
+ private:
+ const beans::NamedValue& mrKey;
+ };
+
+ ::basegfx::B2DHomMatrix getAttributedShapeTransformation( const ::basegfx::B2DRectangle& rShapeBounds,
+ const ShapeAttributeLayerSharedPtr& pAttr )
+ {
+ ::basegfx::B2DHomMatrix aTransform;
+ const ::basegfx::B2DSize& rSize( rShapeBounds.getRange() );
+
+ const double nShearX( pAttr->isShearXAngleValid() ?
+ pAttr->getShearXAngle() :
+ 0.0 );
+ const double nShearY( pAttr->isShearYAngleValid() ?
+ pAttr->getShearYAngle() :
+ 0.0 );
+ const double nRotation( pAttr->isRotationAngleValid() ?
+ pAttr->getRotationAngle()*M_PI/180.0 :
+ 0.0 );
+
+ // scale, shear and rotation pivot point is the shape
+ // center - adapt origin accordingly
+ aTransform.translate( -0.5, -0.5 );
+
+ // ensure valid size (zero size will inevitably lead
+ // to a singular transformation matrix)
+ aTransform.scale( ::basegfx::pruneScaleValue(
+ rSize.getX() ),
+ ::basegfx::pruneScaleValue(
+ rSize.getY() ) );
+
+ const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
+ const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
+ const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );
+
+ if( bNeedRotation || bNeedShearX || bNeedShearY )
+ {
+ if( bNeedShearX )
+ aTransform.shearX( nShearX );
+
+ if( bNeedShearY )
+ aTransform.shearY( nShearY );
+
+ if( bNeedRotation )
+ aTransform.rotate( nRotation );
+ }
+
+ // move left, top corner back to position of the
+ // shape. Since we've already translated the
+ // center of the shape to the origin (the
+ // translate( -0.5, -0.5 ) above), translate to
+ // center of final shape position here.
+ aTransform.translate( rShapeBounds.getCenterX(),
+ rShapeBounds.getCenterY() );
+
+ return aTransform;
+ }
+ }
+
+ // Value extraction from Any
+ // =========================
+
+ /// extract unary double value from Any
+ bool extractValue( double& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& rShape,
+ const ::basegfx::B2DVector& rSlideBounds )
+ {
+ // try to extract numeric value (double, or smaller POD, like float or int)
+ if( (rSourceAny >>= o_rValue) )
+ {
+ // succeeded
+ return true;
+ }
+
+ // try to extract string
+ ::rtl::OUString aString;
+ if( !(rSourceAny >>= aString) )
+ return false; // nothing left to try
+
+ // parse the string into an ExpressionNode
+ try
+ {
+ // Parse string into ExpressionNode, eval node at time 0.0
+ o_rValue = (*SmilFunctionParser::parseSmilValue(
+ aString,
+ calcRelativeShapeBounds(rSlideBounds,
+ rShape->getBounds()) ))(0.0);
+ }
+ catch( ParseError& )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /// extract enum/constant group value from Any
+ bool extractValue( sal_Int32& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& /*rShape*/,
+ const ::basegfx::B2DVector& /*rSlideBounds*/ )
+ {
+ // try to extract numeric value (int, or smaller POD, like byte)
+ if( (rSourceAny >>= o_rValue) )
+ {
+ // succeeded
+ return true;
+ }
+
+ // okay, no plain int. Maybe one of the domain-specific enums?
+ drawing::FillStyle eFillStyle;
+ if( (rSourceAny >>= eFillStyle) )
+ {
+ o_rValue = sal::static_int_cast<sal_Int16>(eFillStyle);
+
+ // succeeded
+ return true;
+ }
+
+ drawing::LineStyle eLineStyle;
+ if( (rSourceAny >>= eLineStyle) )
+ {
+ o_rValue = sal::static_int_cast<sal_Int16>(eLineStyle);
+
+ // succeeded
+ return true;
+ }
+
+ awt::FontSlant eFontSlant;
+ if( (rSourceAny >>= eFontSlant) )
+ {
+ o_rValue = sal::static_int_cast<sal_Int16>(eFontSlant);
+
+ // succeeded
+ return true;
+ }
+
+ // nothing left to try. Failure
+ return false;
+ }
+
+ /// extract enum/constant group value from Any
+ bool extractValue( sal_Int16& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& rShape,
+ const ::basegfx::B2DVector& rSlideBounds )
+ {
+ sal_Int32 aValue;
+ if( !extractValue(aValue,rSourceAny,rShape,rSlideBounds) )
+ return false;
+
+ if( std::numeric_limits<sal_Int16>::max() < aValue ||
+ std::numeric_limits<sal_Int16>::min() > aValue )
+ {
+ return false;
+ }
+
+ o_rValue = static_cast<sal_Int16>(aValue);
+
+ return true;
+ }
+
+ /// extract color value from Any
+ bool extractValue( RGBColor& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& /*rShape*/,
+ const ::basegfx::B2DVector& /*rSlideBounds*/ )
+ {
+ // try to extract numeric value (double, or smaller POD, like float or int)
+ {
+ double nTmp = 0;
+ if( (rSourceAny >>= nTmp) )
+ {
+ sal_uInt32 aIntColor( static_cast< sal_uInt32 >(nTmp) );
+
+ // TODO(F2): Handle color values correctly, here
+ o_rValue = unoColor2RGBColor( aIntColor );
+
+ // succeeded
+ return true;
+ }
+ }
+
+ // try double sequence
+ {
+ uno::Sequence< double > aTmp;
+ if( (rSourceAny >>= aTmp) )
+ {
+ ENSURE_OR_THROW( aTmp.getLength() == 3,
+ "extractValue(): inappropriate length for RGB color value" );
+
+ o_rValue = RGBColor( aTmp[0], aTmp[1], aTmp[2] );
+
+ // succeeded
+ return true;
+ }
+ }
+
+ // try sal_Int32 sequence
+ {
+ uno::Sequence< sal_Int32 > aTmp;
+ if( (rSourceAny >>= aTmp) )
+ {
+ ENSURE_OR_THROW( aTmp.getLength() == 3,
+ "extractValue(): inappropriate length for RGB color value" );
+
+ // truncate to byte
+ o_rValue = RGBColor( ::cppcanvas::makeColor(
+ static_cast<sal_uInt8>(aTmp[0]),
+ static_cast<sal_uInt8>(aTmp[1]),
+ static_cast<sal_uInt8>(aTmp[2]),
+ 255 ) );
+
+ // succeeded
+ return true;
+ }
+ }
+
+ // try sal_Int8 sequence
+ {
+ uno::Sequence< sal_Int8 > aTmp;
+ if( (rSourceAny >>= aTmp) )
+ {
+ ENSURE_OR_THROW( aTmp.getLength() == 3,
+ "extractValue(): inappropriate length for RGB color value" );
+
+ o_rValue = RGBColor( ::cppcanvas::makeColor( aTmp[0], aTmp[1], aTmp[2], 255 ) );
+
+ // succeeded
+ return true;
+ }
+ }
+
+ // try to extract string
+ ::rtl::OUString aString;
+ if( !(rSourceAny >>= aString) )
+ return false; // nothing left to try
+
+ // TODO(F2): Provide symbolic color values here
+ o_rValue = RGBColor( 0.5, 0.5, 0.5 );
+
+ return true;
+ }
+
+ /// extract color value from Any
+ bool extractValue( HSLColor& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& /*rShape*/,
+ const ::basegfx::B2DVector& /*rSlideBounds*/ )
+ {
+ // try double sequence
+ {
+ uno::Sequence< double > aTmp;
+ if( (rSourceAny >>= aTmp) )
+ {
+ ENSURE_OR_THROW( aTmp.getLength() == 3,
+ "extractValue(): inappropriate length for HSL color value" );
+
+ o_rValue = HSLColor( aTmp[0], aTmp[1], aTmp[2] );
+
+ // succeeded
+ return true;
+ }
+ }
+
+ // try sal_Int8 sequence
+ {
+ uno::Sequence< sal_Int8 > aTmp;
+ if( (rSourceAny >>= aTmp) )
+ {
+ ENSURE_OR_THROW( aTmp.getLength() == 3,
+ "extractValue(): inappropriate length for HSL color value" );
+
+ o_rValue = HSLColor( aTmp[0]*360.0/255.0, aTmp[1]/255.0, aTmp[2]/255.0 );
+
+ // succeeded
+ return true;
+ }
+ }
+
+ return false; // nothing left to try
+ }
+
+ /// extract plain string from Any
+ bool extractValue( ::rtl::OUString& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& /*rShape*/,
+ const ::basegfx::B2DVector& /*rSlideBounds*/ )
+ {
+ // try to extract string
+ if( !(rSourceAny >>= o_rValue) )
+ return false; // nothing left to try
+
+ return true;
+ }
+
+ /// extract bool value from Any
+ bool extractValue( bool& o_rValue,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& /*rShape*/,
+ const ::basegfx::B2DVector& /*rSlideBounds*/ )
+ {
+ sal_Bool nTmp = sal_Bool();
+ // try to extract bool value
+ if( (rSourceAny >>= nTmp) )
+ {
+ o_rValue = nTmp;
+
+ // succeeded
+ return true;
+ }
+
+ // try to extract string
+ ::rtl::OUString aString;
+ if( !(rSourceAny >>= aString) )
+ return false; // nothing left to try
+
+ // we also take the strings "true" and "false",
+ // as well as "on" and "off" here
+ if( aString.equalsIgnoreAsciiCaseAscii("true") ||
+ aString.equalsIgnoreAsciiCaseAscii("on") )
+ {
+ o_rValue = true;
+ return true;
+ }
+ if( aString.equalsIgnoreAsciiCaseAscii("false") ||
+ aString.equalsIgnoreAsciiCaseAscii("off") )
+ {
+ o_rValue = false;
+ return true;
+ }
+
+ // ultimately failed.
+ return false;
+ }
+
+ /// extract double 2-tuple from Any
+ bool extractValue( ::basegfx::B2DTuple& o_rPair,
+ const uno::Any& rSourceAny,
+ const ShapeSharedPtr& rShape,
+ const ::basegfx::B2DVector& rSlideBounds )
+ {
+ animations::ValuePair aPair;
+
+ if( !(rSourceAny >>= aPair) )
+ return false;
+
+ double nFirst;
+ if( !extractValue( nFirst, aPair.First, rShape, rSlideBounds ) )
+ return false;
+
+ double nSecond;
+ if( !extractValue( nSecond, aPair.Second, rShape, rSlideBounds ) )
+ return false;
+
+ o_rPair.setX( nFirst );
+ o_rPair.setY( nSecond );
+
+ return true;
+ }
+
+ bool findNamedValue( uno::Sequence< beans::NamedValue > const& rSequence,
+ const beans::NamedValue& rSearchKey )
+ {
+ const beans::NamedValue* pArray = rSequence.getConstArray();
+ const size_t nLen( rSequence.getLength() );
+
+ if( nLen == 0 )
+ return false;
+
+ const beans::NamedValue* pFound = ::std::find_if( pArray,
+ pArray + nLen,
+ NamedValueComparator( rSearchKey ) );
+
+ if( pFound == pArray + nLen )
+ return false;
+
+ return true;
+ }
+
+ bool findNamedValue( beans::NamedValue* o_pRet,
+ const uno::Sequence< beans::NamedValue >& rSequence,
+ const ::rtl::OUString& rSearchString )
+ {
+ const beans::NamedValue* pArray = rSequence.getConstArray();
+ const size_t nLen( rSequence.getLength() );
+
+ if( nLen == 0 )
+ return false;
+
+ const beans::NamedValue* pFound = ::std::find_if( pArray,
+ pArray + nLen,
+ NamedValueStringComparator( rSearchString ) );
+ if( pFound == pArray + nLen )
+ return false;
+
+ if( o_pRet )
+ *o_pRet = *pFound;
+
+ return true;
+ }
+
+ basegfx::B2DRange calcRelativeShapeBounds( const basegfx::B2DVector& rPageSize,
+ const basegfx::B2DRange& rShapeBounds )
+ {
+ return basegfx::B2DRange( rShapeBounds.getMinX() / rPageSize.getX(),
+ rShapeBounds.getMinY() / rPageSize.getY(),
+ rShapeBounds.getMaxX() / rPageSize.getX(),
+ rShapeBounds.getMaxY() / rPageSize.getY() );
+ }
+
+ // TODO(F2): Currently, the positional attributes DO NOT mirror the XShape properties.
+ // First and foremost, this is because we must operate with the shape boundrect,
+ // not position and size (the conversion between logic rect, snap rect and boundrect
+ // are non-trivial for draw shapes, and I won't duplicate them here). Thus, shapes
+ // rotated on the page will still have 0.0 rotation angle, as the metafile
+ // representation fetched over the API is our default zero case.
+
+ ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle& rShapeBounds,
+ const ShapeAttributeLayerSharedPtr& pAttr )
+ {
+ if( !pAttr )
+ {
+ const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(
+ rShapeBounds.getWidth(), rShapeBounds.getHeight(),
+ rShapeBounds.getMinX(), rShapeBounds.getMinY()));
+
+ return aTransform;
+ }
+ else
+ {
+ return getAttributedShapeTransformation( rShapeBounds,
+ pAttr );
+ }
+ }
+
+ ::basegfx::B2DHomMatrix getSpriteTransformation( const ::basegfx::B2DVector& rPixelSize,
+ const ::basegfx::B2DVector& rOrigSize,
+ const ShapeAttributeLayerSharedPtr& pAttr )
+ {
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if( pAttr )
+ {
+ const double nShearX( pAttr->isShearXAngleValid() ?
+ pAttr->getShearXAngle() :
+ 0.0 );
+ const double nShearY( pAttr->isShearYAngleValid() ?
+ pAttr->getShearYAngle() :
+ 0.0 );
+ const double nRotation( pAttr->isRotationAngleValid() ?
+ pAttr->getRotationAngle()*M_PI/180.0 :
+ 0.0 );
+
+ // scale, shear and rotation pivot point is the
+ // sprite's pixel center - adapt origin accordingly
+ aTransform.translate( -0.5*rPixelSize.getX(),
+ -0.5*rPixelSize.getY() );
+
+ const ::basegfx::B2DSize aSize(
+ pAttr->isWidthValid() ? pAttr->getWidth() : rOrigSize.getX(),
+ pAttr->isHeightValid() ? pAttr->getHeight() : rOrigSize.getY() );
+
+ // ensure valid size (zero size will inevitably lead
+ // to a singular transformation matrix).
+ aTransform.scale( ::basegfx::pruneScaleValue(
+ aSize.getX() /
+ ::basegfx::pruneScaleValue(
+ rOrigSize.getX() ) ),
+ ::basegfx::pruneScaleValue(
+ aSize.getY() /
+ ::basegfx::pruneScaleValue(
+ rOrigSize.getY() ) ) );
+
+ const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
+ const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
+ const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );
+
+ if( bNeedRotation || bNeedShearX || bNeedShearY )
+ {
+ if( bNeedShearX )
+ aTransform.shearX( nShearX );
+
+ if( bNeedShearY )
+ aTransform.shearY( nShearY );
+
+ if( bNeedRotation )
+ aTransform.rotate( nRotation );
+ }
+
+ // move left, top corner back to original position of
+ // the sprite (we've translated the center of the
+ // sprite to the origin above).
+ aTransform.translate( 0.5*rPixelSize.getX(),
+ 0.5*rPixelSize.getY() );
+ }
+
+ // return identity transform for un-attributed
+ // shapes. This renders the sprite as-is, in it's
+ // document-supplied size.
+ return aTransform;
+ }
+
+ ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle& rUnitBounds,
+ const ::basegfx::B2DHomMatrix& rShapeTransform,
+ const ShapeAttributeLayerSharedPtr& pAttr )
+ {
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if( pAttr &&
+ pAttr->isCharScaleValid() &&
+ fabs(pAttr->getCharScale()) > 1.0 )
+ {
+ // enlarge shape bounds. Have to consider the worst
+ // case here (the text fully fills the shape)
+
+ const double nCharScale( pAttr->getCharScale() );
+
+ // center of scaling is the middle of the shape
+ aTransform.translate( -0.5, -0.5 );
+ aTransform.scale( nCharScale, nCharScale );
+ aTransform.translate( 0.5, 0.5 );
+ }
+
+ aTransform *= rShapeTransform;
+
+ ::basegfx::B2DRectangle aRes;
+
+ // apply shape transformation to unit rect
+ return ::canvas::tools::calcTransformedRectBounds(
+ aRes,
+ rUnitBounds,
+ aTransform );
+ }
+
+ ::basegfx::B2DRange getShapeUpdateArea( const ::basegfx::B2DRange& rUnitBounds,
+ const ::basegfx::B2DRange& rShapeBounds )
+ {
+ return ::basegfx::B2DRectangle(
+ basegfx::tools::lerp( rShapeBounds.getMinX(),
+ rShapeBounds.getMaxX(),
+ rUnitBounds.getMinX() ),
+ basegfx::tools::lerp( rShapeBounds.getMinY(),
+ rShapeBounds.getMaxY(),
+ rUnitBounds.getMinY() ),
+ basegfx::tools::lerp( rShapeBounds.getMinX(),
+ rShapeBounds.getMaxX(),
+ rUnitBounds.getMaxX() ),
+ basegfx::tools::lerp( rShapeBounds.getMinY(),
+ rShapeBounds.getMaxY(),
+ rUnitBounds.getMaxY() ) );
+ }
+
+ ::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle& rOrigBounds,
+ const ShapeAttributeLayerSharedPtr& pAttr )
+ {
+ // an already empty shape bound need no further
+ // treatment. In fact, any changes applied below would
+ // actually remove the special empty state, thus, don't
+ // change!
+ if( !pAttr ||
+ rOrigBounds.isEmpty() )
+ {
+ return rOrigBounds;
+ }
+ else
+ {
+ // cannot use maBounds anymore, attributes might have been
+ // changed by now.
+ // Have to use absolute values here, as negative sizes
+ // (aka mirrored shapes) _still_ have the same bounds,
+ // only with mirrored content.
+ ::basegfx::B2DSize aSize;
+ aSize.setX( fabs( pAttr->isWidthValid() ?
+ pAttr->getWidth() :
+ rOrigBounds.getWidth() ) );
+ aSize.setY( fabs( pAttr->isHeightValid() ?
+ pAttr->getHeight() :
+ rOrigBounds.getHeight() ) );
+
+ ::basegfx::B2DPoint aPos;
+ aPos.setX( pAttr->isPosXValid() ?
+ pAttr->getPosX() :
+ rOrigBounds.getCenterX() );
+ aPos.setY( pAttr->isPosYValid() ?
+ pAttr->getPosY() :
+ rOrigBounds.getCenterY() );
+
+ // the positional attribute retrieved from the
+ // ShapeAttributeLayer actually denotes the _middle_
+ // of the shape (do it as the PPTs do...)
+ return ::basegfx::B2DRectangle( aPos - 0.5*aSize,
+ aPos + 0.5*aSize );
+ }
+ }
+
+ RGBColor unoColor2RGBColor( sal_Int32 nColor )
+ {
+ return RGBColor(
+ ::cppcanvas::makeColor(
+ // convert from API color to IntSRGBA color
+ // (0xAARRGGBB -> 0xRRGGBBAA)
+ static_cast< sal_uInt8 >( nColor >> 16U ),
+ static_cast< sal_uInt8 >( nColor >> 8U ),
+ static_cast< sal_uInt8 >( nColor ),
+ static_cast< sal_uInt8 >( nColor >> 24U ) ) );
+ }
+
+ sal_Int32 RGBAColor2UnoColor( ::cppcanvas::Color::IntSRGBA aColor )
+ {
+ return ::cppcanvas::makeColorARGB(
+ // convert from IntSRGBA color to API color
+ // (0xRRGGBBAA -> 0xAARRGGBB)
+ static_cast< sal_uInt8 >(0),
+ ::cppcanvas::getRed(aColor),
+ ::cppcanvas::getGreen(aColor),
+ ::cppcanvas::getBlue(aColor));
+ }
+
+ /*sal_Int32 RGBAColor2UnoColor( ::cppcanvas::Color::IntSRGBA aColor )
+ {
+ return ::cppcanvas::unMakeColor(
+ // convert from IntSRGBA color to API color
+ // (0xRRGGBBAA -> 0xAARRGGBB)
+ static_cast< sal_uInt8 >(0),
+ ::cppcanvas::getRed(aColor),
+ ::cppcanvas::getGreen(aColor),
+ ::cppcanvas::getBlue(aColor));
+ }*/
+
+ sal_Int8 unSignedToSigned(sal_Int8 nInt)
+ {
+ if(nInt < 0 ){
+ sal_Int8 nInt2 = nInt >> 1U;
+ return nInt2;
+ }else{
+ return nInt;
+ }
+ }
+
+ void fillRect( const ::cppcanvas::CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2DRectangle& rRect,
+ ::cppcanvas::Color::IntSRGBA aFillColor )
+ {
+ const ::basegfx::B2DPolygon aPoly(
+ ::basegfx::tools::createPolygonFromRect( rRect ));
+
+ ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
+ ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( rCanvas,
+ aPoly ) );
+
+ if( pPolyPoly )
+ {
+ pPolyPoly->setRGBAFillColor( aFillColor );
+ pPolyPoly->draw();
+ }
+ }
+
+ void initSlideBackground( const ::cppcanvas::CanvasSharedPtr& rCanvas,
+ const ::basegfx::B2ISize& rSize )
+ {
+ ::cppcanvas::CanvasSharedPtr pCanvas( rCanvas->clone() );
+
+ // set transformation to identitiy (->device pixel)
+ pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // #i42440# Fill the _full_ background in
+ // black. Since we had to extend the bitmap by one
+ // pixel, and the bitmap is initialized white,
+ // depending on the slide content a one pixel wide
+ // line will show to the bottom and the right.
+ fillRect( pCanvas,
+ ::basegfx::B2DRectangle( 0.0, 0.0,
+ rSize.getX(),
+ rSize.getY() ),
+ 0x000000FFU );
+
+ // fill the bounds rectangle in white. Subtract one pixel
+ // from both width and height, because the slide size is
+ // chosen one pixel larger than given by the drawing
+ // layer. This is because shapes with line style, that
+ // have the size of the slide would otherwise be cut
+ // off. OTOH, every other slide background (solid fill,
+ // gradient, bitmap) render one pixel less, thus revealing
+ // ugly white pixel to the right and the bottom.
+ fillRect( pCanvas,
+ ::basegfx::B2DRectangle( 0.0, 0.0,
+ rSize.getX()-1,
+ rSize.getY()-1 ),
+ 0xFFFFFFFFU );
+ }
+
+ ::basegfx::B2DRectangle getAPIShapeBounds( const uno::Reference< drawing::XShape >& xShape )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xShape,
+ uno::UNO_QUERY_THROW );
+ // read bound rect
+ awt::Rectangle aTmpRect;
+ if( !(xPropSet->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BoundRect") ) ) >>= aTmpRect) )
+ {
+ ENSURE_OR_THROW( false,
+ "getAPIShapeBounds(): Could not get \"BoundRect\" property from shape" );
+ }
+
+ return ::basegfx::B2DRectangle( aTmpRect.X,
+ aTmpRect.Y,
+ aTmpRect.X+aTmpRect.Width,
+ aTmpRect.Y+aTmpRect.Height );
+ }
+
+ double getAPIShapePrio( const uno::Reference< drawing::XShape >& xShape )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xShape,
+ uno::UNO_QUERY_THROW );
+ // read prio
+ sal_Int32 nPrio(0);
+ if( !(xPropSet->getPropertyValue(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ZOrder") ) ) >>= nPrio) )
+ {
+ ENSURE_OR_THROW( false,
+ "getAPIShapePrio(): Could not get \"ZOrder\" property from shape" );
+ }
+
+ // TODO(F2): Check and adapt the range of possible values here.
+ // Maybe we can also take the total number of shapes here
+ return nPrio / 65535.0;
+ }
+
+ basegfx::B2IVector getSlideSizePixel( const basegfx::B2DVector& rSlideSize,
+ const UnoViewSharedPtr& pView )
+ {
+ ENSURE_OR_THROW(pView, "getSlideSizePixel(): invalid view");
+
+ // determine transformed page bounds
+ const basegfx::B2DRange aRect( 0,0,
+ rSlideSize.getX(),
+ rSlideSize.getY() );
+ basegfx::B2DRange aTmpRect;
+ canvas::tools::calcTransformedRectBounds( aTmpRect,
+ aRect,
+ pView->getTransformation() );
+
+ // #i42440# Returned slide size is one pixel too small, as
+ // rendering happens one pixel to the right and below the
+ // actual bound rect.
+ return basegfx::B2IVector(
+ basegfx::fround( aTmpRect.getRange().getX() ) + 1,
+ basegfx::fround( aTmpRect.getRange().getY() ) + 1 );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/barndoorwipe.cxx b/slideshow/source/engine/transitions/barndoorwipe.cxx
new file mode 100644
index 000000000000..abae768bef81
--- /dev/null
+++ b/slideshow/source/engine/transitions/barndoorwipe.cxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "barndoorwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon BarnDoorWipe::operator () ( double t )
+{
+ if (m_doubled)
+ t /= 2.0;
+
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5));
+ aTransform.scale( ::basegfx::pruneScaleValue(t), 1.0 );
+ aTransform.translate( 0.5, 0.5 );
+ ::basegfx::B2DPolygon poly( m_unitRect );
+ poly.transform( aTransform );
+ ::basegfx::B2DPolyPolygon res(poly);
+
+ if (m_doubled) {
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5);
+ aTransform.rotate( M_PI_2 );
+ aTransform.translate( 0.5, 0.5 );
+ poly.transform( aTransform );
+ res.append(poly);
+ }
+
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/barndoorwipe.hxx b/slideshow/source/engine/transitions/barndoorwipe.hxx
new file mode 100644
index 000000000000..b8683e38f857
--- /dev/null
+++ b/slideshow/source/engine/transitions/barndoorwipe.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_BARNDOORWIPE_HXX
+#define INCLUDED_SLIDESHOW_BARNDOORWIPE_HXX
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a barn door wipe or double barn door wipe:
+class BarnDoorWipe : public ParametricPolyPolygon
+{
+public:
+ BarnDoorWipe( bool doubled = false )
+ : m_unitRect( createUnitRect() ), m_doubled(doubled) {}
+ virtual ::basegfx::B2DPolyPolygon operator()( double x );
+private:
+ const ::basegfx::B2DPolygon m_unitRect;
+ const bool m_doubled;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_BARNDOORWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/barwipepolypolygon.cxx b/slideshow/source/engine/transitions/barwipepolypolygon.cxx
new file mode 100644
index 000000000000..c1d263ffa06b
--- /dev/null
+++ b/slideshow/source/engine/transitions/barwipepolypolygon.cxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include "barwipepolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon BarWipePolyPolygon::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res;
+ ::basegfx::B2DHomMatrix aTransform;
+ aTransform.scale( ::basegfx::pruneScaleValue( t / m_nBars ), 1.0 );
+ for ( sal_Int32 i = m_nBars; i--; )
+ {
+ ::basegfx::B2DHomMatrix transform( aTransform );
+ transform.translate( static_cast<double>(i) / m_nBars, 0.0 );
+ ::basegfx::B2DPolygon poly( m_unitRect );
+ poly.transform( transform );
+ res.append( poly );
+ }
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/barwipepolypolygon.hxx b/slideshow/source/engine/transitions/barwipepolypolygon.hxx
new file mode 100644
index 000000000000..6c7b78959a23
--- /dev/null
+++ b/slideshow/source/engine/transitions/barwipepolypolygon.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_BARWIPEPOLYPOLYGON_HXX
+#define INCLUDED_SLIDESHOW_BARWIPEPOLYPOLYGON_HXX
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a horizontal, left-to-right bar wipe:
+class BarWipePolyPolygon : public ParametricPolyPolygon
+{
+public:
+ BarWipePolyPolygon( sal_Int32 nBars = 1 /* nBars > 1: blinds effect */ )
+ : m_nBars(nBars),
+ m_unitRect( createUnitRect() )
+ {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ const sal_Int32 m_nBars;
+ const ::basegfx::B2DPolygon m_unitRect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_BARWIPEPOLYPOLYGON_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/boxwipe.cxx b/slideshow/source/engine/transitions/boxwipe.cxx
new file mode 100644
index 000000000000..0ecfe203ecdf
--- /dev/null
+++ b/slideshow/source/engine/transitions/boxwipe.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include "boxwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon BoxWipe::operator () ( double t )
+{
+ ::basegfx::B2DHomMatrix aTransform;
+ double d = ::basegfx::pruneScaleValue(t);
+ if (m_topCentered) {
+ aTransform.translate( -0.5, 0.0 );
+ aTransform.scale( d, d );
+ aTransform.translate( 0.5, 0.0 );
+ } else {
+ aTransform.scale( d, d );
+ }
+
+ ::basegfx::B2DPolyPolygon res( m_unitRect );
+ res.transform( aTransform );
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/boxwipe.hxx b/slideshow/source/engine/transitions/boxwipe.hxx
new file mode 100644
index 000000000000..fe44113d54a1
--- /dev/null
+++ b/slideshow/source/engine/transitions/boxwipe.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_BOXWIPE_HXX
+#define INCLUDED_SLIDESHOW_BOXWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a default topleft to right bottom box wipe
+class BoxWipe : public ParametricPolyPolygon
+{
+public:
+ BoxWipe( bool topCentered ) : m_topCentered(topCentered),
+ m_unitRect( createUnitRect() )
+ {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ const bool m_topCentered;
+ const ::basegfx::B2DPolyPolygon m_unitRect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_BOXWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/checkerboardwipe.cxx b/slideshow/source/engine/transitions/checkerboardwipe.cxx
new file mode 100644
index 000000000000..8db1b023c5f9
--- /dev/null
+++ b/slideshow/source/engine/transitions/checkerboardwipe.cxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include "checkerboardwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon CheckerBoardWipe::operator () ( double t )
+{
+ const double d = (1.0 / m_unitsPerEdge);
+ ::basegfx::B2DHomMatrix aTransform;
+ aTransform.scale( ::basegfx::pruneScaleValue( d * 2.0 * t ),
+ ::basegfx::pruneScaleValue( d ) );
+
+ ::basegfx::B2DPolyPolygon res;
+ for ( sal_Int32 i = m_unitsPerEdge; i--; )
+ {
+ ::basegfx::B2DHomMatrix transform( aTransform );
+ if ((i % 2) == 1) // odd line
+ transform.translate( -d, 0.0 );
+ for ( sal_Int32 j = (m_unitsPerEdge / 2) + 1; j--; )
+ {
+ ::basegfx::B2DPolyPolygon poly( m_unitRect );
+ poly.transform( transform );
+ res.append( poly );
+ transform.translate( d * 2.0, 0.0 );
+ }
+ aTransform.translate( 0.0, d ); // next line
+ }
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/checkerboardwipe.hxx b/slideshow/source/engine/transitions/checkerboardwipe.hxx
new file mode 100644
index 000000000000..df83391e20ee
--- /dev/null
+++ b/slideshow/source/engine/transitions/checkerboardwipe.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_CHECKERBOARDWIPE_HXX
+#define INCLUDED_SLIDESHOW_CHECKERBOARDWIPE_HXX
+
+#include <osl/diagnose.h>
+
+#include "transitiontools.hxx"
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a check board wipe (across)
+class CheckerBoardWipe : public ParametricPolyPolygon
+{
+public:
+ CheckerBoardWipe( sal_Int32 unitsPerEdge = 10 )
+ : m_unitsPerEdge(unitsPerEdge),
+ m_unitRect( createUnitRect() )
+ { OSL_ASSERT( (unitsPerEdge % 2) == 0 ); }
+ virtual ::basegfx::B2DPolyPolygon operator () ( double x );
+private:
+ const sal_Int32 m_unitsPerEdge;
+ const ::basegfx::B2DPolyPolygon m_unitRect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_CHECKERBOARDWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/clippingfunctor.cxx b/slideshow/source/engine/transitions/clippingfunctor.cxx
new file mode 100644
index 000000000000..4b4e148bcee3
--- /dev/null
+++ b/slideshow/source/engine/transitions/clippingfunctor.cxx
@@ -0,0 +1,241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include "clippingfunctor.hxx"
+#include "transitiontools.hxx"
+
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ClippingFunctor::ClippingFunctor(const ParametricPolyPolygonSharedPtr& rPolygon,
+ const TransitionInfo& rTransitionInfo,
+ bool bDirectionForward,
+ bool bModeIn ) :
+ mpParametricPoly( rPolygon ),
+ maStaticTransformation(),
+ // AW: Not needed
+ // maBackgroundRect( createUnitRect() ),
+ mbForwardParameterSweep( true ),
+ mbSubtractPolygon( false ),
+ mbScaleIsotrophically( rTransitionInfo.mbScaleIsotrophically ),
+ mbFlip(false)
+ {
+ ENSURE_OR_THROW( rPolygon,
+ "ClippingFunctor::ClippingFunctor(): Invalid parametric polygon" );
+
+ // maBackgroundRect serves as the minuent when
+ // subtracting a given clip polygon from the
+ // background. To speed up the clipper algo, avoid
+ // actual intersections of the generated
+ // poly-polygon with the minuent - i.e. choose the
+ // polygon to subtract from sufficiently large.
+
+ // blow up unit rect to (-1,-1),(2,2)
+ // AW: Not needed, just use range
+ // ::basegfx::B2DHomMatrix aMatrix;
+ // aMatrix.scale(3.0,3.0);
+ // aMatrix.translate(-1.0,-1.0);
+ // maBackgroundRect.transform( aMatrix );
+
+ // extract modification info from maTransitionInfo
+ // -----------------------------------------------
+
+ // perform general transformations _before_ the reverse
+ // mode changes. This allows the Transition table to be
+ // filled more constitently (otherwise, when e.g. rotating
+ // a clip 90 degrees, the REVERSEMETHOD_FLIP_X becomes
+ // REVERSEMETHOD_FLIP_Y instead)
+ if (rTransitionInfo.mnRotationAngle != 0.0 ||
+ rTransitionInfo.mnScaleX != 1.0 ||
+ rTransitionInfo.mnScaleY != 1.0)
+ {
+ maStaticTransformation.translate( -0.5, -0.5 );
+ // apply further transformations:
+ if (rTransitionInfo.mnRotationAngle != 0.0)
+ {
+ maStaticTransformation.rotate(
+ basegfx::deg2rad(rTransitionInfo.mnRotationAngle) );
+ }
+ if (rTransitionInfo.mnScaleX != 1.0 ||
+ rTransitionInfo.mnScaleY != 1.0)
+ {
+ maStaticTransformation.scale(
+ rTransitionInfo.mnScaleX,
+ rTransitionInfo.mnScaleY );
+ }
+ maStaticTransformation.translate( 0.5, 0.5 );
+ }
+
+ if( !bDirectionForward )
+ {
+ // Client has requested reversed
+ // direction. Apply TransitionInfo's choice
+ // for that
+ switch( rTransitionInfo.meReverseMethod )
+ {
+ default:
+ ENSURE_OR_THROW(
+ false,
+ "TransitionFactory::TransitionFactory(): Unexpected reverse method" );
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_IGNORE:
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_INVERT_SWEEP:
+ mbForwardParameterSweep = !mbForwardParameterSweep;
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_SUBTRACT_POLYGON:
+ mbSubtractPolygon = !mbSubtractPolygon;
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT:
+ mbForwardParameterSweep = !mbForwardParameterSweep;
+ mbSubtractPolygon = !mbSubtractPolygon;
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_ROTATE_180:
+ maStaticTransformation = basegfx::tools::createRotateAroundPoint(0.5, 0.5, M_PI)
+ * maStaticTransformation;
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_FLIP_X:
+ maStaticTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(-1.0, 1.0, 1.0, 0.0)
+ * maStaticTransformation;
+ mbFlip = true;
+ break;
+
+ case TransitionInfo::REVERSEMETHOD_FLIP_Y:
+ maStaticTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(1.0, -1.0, 0.0, 1.0)
+ * maStaticTransformation;
+ mbFlip = true;
+ break;
+ }
+ }
+
+ if( !bModeIn )
+ {
+ // client has requested 'out' mode. Apply
+ // TransitionInfo's method of choice
+ if( rTransitionInfo.mbOutInvertsSweep )
+ mbForwardParameterSweep = !mbForwardParameterSweep;
+ else
+ mbSubtractPolygon = !mbSubtractPolygon;
+ }
+ }
+
+ ::basegfx::B2DPolyPolygon ClippingFunctor::operator()( double nValue,
+ const ::basegfx::B2DSize& rTargetSize )
+ {
+ // modify clip polygon according to static
+ // transformation plus current shape size
+ ::basegfx::B2DHomMatrix aMatrix( maStaticTransformation );
+
+ // retrieve current clip polygon
+ ::basegfx::B2DPolyPolygon aClipPoly = (*mpParametricPoly)(
+ mbForwardParameterSweep ? nValue : 1.0 - nValue );
+
+ // TODO(Q4): workaround here, better be fixed in cppcanvas
+ if (aClipPoly.count() == 0)
+ aClipPoly.append( basegfx::B2DPolygon() );
+
+ if (mbFlip)
+ aClipPoly.flip();
+
+ // currently, clipper cannot cope with curves. Subdivide first
+ // AW: Should be no longer necessary; clipping tools are now bezier-safe
+ // if( aClipPoly.areControlPointsUsed() )
+ // aClipPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aClipPoly);
+
+ if( mbSubtractPolygon )
+ {
+ // subtract given polygon from background
+ // rect. Do that before any transformations.
+
+ // calc maBackgroundRect \ aClipPoly
+ // =================================
+
+ // AW: Simplified
+ // use a range with fixed size (-1,-1),(2,2)
+ const basegfx::B2DRange aBackgroundRange(-1, -1, 2, 2);
+ const basegfx::B2DRange aClipPolyRange(aClipPoly.getB2DRange());
+
+ if(aBackgroundRange.isInside(aClipPolyRange))
+ {
+ // combine polygons; make the clip polygon the hole
+ aClipPoly = ::basegfx::tools::correctOrientations(aClipPoly);
+ aClipPoly.flip();
+ aClipPoly.insert(0, basegfx::tools::createPolygonFromRect(aBackgroundRange));
+ }
+ else
+ {
+ // when not completely inside aBackgroundRange clipping is needed
+ // substract aClipPoly from aBackgroundRange
+ const basegfx::B2DPolyPolygon aBackgroundPolyPoly(basegfx::tools::createPolygonFromRect(aBackgroundRange));
+ aClipPoly = basegfx::tools::solvePolygonOperationDiff(aBackgroundPolyPoly, aClipPoly);
+ }
+ }
+
+ // scale polygon up to current shape size
+ if( mbScaleIsotrophically )
+ {
+ const double nScale( ::std::max( rTargetSize.getX(),
+ rTargetSize.getY() ) );
+ aMatrix.scale( nScale, nScale );
+ aMatrix.translate( -(nScale-rTargetSize.getX())/2.0,
+ -(nScale-rTargetSize.getY())/2.0 );
+ }
+ else
+ {
+ aMatrix.scale( rTargetSize.getX(),
+ rTargetSize.getY() );
+ }
+
+ // apply cumulative transformation to clip polygon
+ aClipPoly.transform( aMatrix );
+
+ return aClipPoly;
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/clippingfunctor.hxx b/slideshow/source/engine/transitions/clippingfunctor.hxx
new file mode 100644
index 000000000000..e02af2d148bc
--- /dev/null
+++ b/slideshow/source/engine/transitions/clippingfunctor.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_CLIPPINGFUNCTOR_HXX
+#define INCLUDED_SLIDESHOW_CLIPPINGFUNCTOR_HXX
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <transitioninfo.hxx>
+#include <parametricpolypolygon.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Generates the final clipping polygon.
+
+ This class serves as the functor, which generates the
+ final clipping polygon from a given ParametricPolyPolygon
+ and a TransitionInfo.
+
+ The ParametricPolyPolygon can be obtained from the
+ ParametricPolyPolygonFactory, see there.
+
+ The TransitionInfo further parameterizes the polygon
+ generated by the ParametricPolyPolygon, with common
+ modifications such as rotation, flipping, or change of
+ direction. This allows the ParametricPolyPolygonFactory to
+ provide only prototypical shapes, with the ClippingFunctor
+ further customizing the output.
+ */
+ class ClippingFunctor
+ {
+ public:
+ ClippingFunctor(
+ const ParametricPolyPolygonSharedPtr& rPolygon,
+ const TransitionInfo& rTransitionInfo,
+ bool bDirectionForward,
+ bool bModeIn );
+
+ /** Generate clip polygon.
+
+ @param nValue
+ Value to generate the polygon for. Must be in the
+ range [0,1].
+
+ @param rTargetSize
+ Size the clip polygon should cover. This is typically
+ the size of the object the effect is applied on.
+ */
+ ::basegfx::B2DPolyPolygon operator()( double nValue,
+ const ::basegfx::B2DSize& rTargetSize );
+
+ private:
+ ParametricPolyPolygonSharedPtr mpParametricPoly;
+ ::basegfx::B2DHomMatrix maStaticTransformation;
+ // AW: Not needed
+ // ::basegfx::B2DPolyPolygon maBackgroundRect;
+ bool mbForwardParameterSweep;
+ bool mbSubtractPolygon;
+ const bool mbScaleIsotrophically;
+ bool mbFlip;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_CLIPPINGFUNCTOR_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/clockwipe.cxx b/slideshow/source/engine/transitions/clockwipe.cxx
new file mode 100644
index 000000000000..4f9773791901
--- /dev/null
+++ b/slideshow/source/engine/transitions/clockwipe.cxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "clockwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolygon ClockWipe::calcCenteredClock( double t, double e )
+{
+ ::basegfx::B2DPolygon poly;
+ ::basegfx::B2DHomMatrix aTransform;
+ aTransform.rotate( t * 2.0 * M_PI );
+ const double MAX_EDGE = 2.0;
+ ::basegfx::B2DPoint p( 0.0, -MAX_EDGE );
+ p *= aTransform;
+ poly.append( p );
+ if (t >= 0.875)
+ poly.append( ::basegfx::B2DPoint( -e, -e ) );
+ if (t >= 0.625)
+ poly.append( ::basegfx::B2DPoint( -e, e ) );
+ if (t >= 0.375)
+ poly.append( ::basegfx::B2DPoint( e, e ) );
+ if (t >= 0.125)
+ poly.append( ::basegfx::B2DPoint( e, -e ) );
+ poly.append( ::basegfx::B2DPoint( 0.0, -e ) );
+ poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) );
+ poly.setClosed(true);
+ return poly;
+}
+
+::basegfx::B2DPolyPolygon ClockWipe::operator () ( double t )
+{
+ const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5));
+ ::basegfx::B2DPolygon poly( calcCenteredClock(t) );
+ poly.transform( aTransform );
+ return ::basegfx::B2DPolyPolygon(poly);
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/clockwipe.hxx b/slideshow/source/engine/transitions/clockwipe.hxx
new file mode 100644
index 000000000000..bfa45cdb9f79
--- /dev/null
+++ b/slideshow/source/engine/transitions/clockwipe.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_CLOCKWIPE_HXX
+#define INCLUDED_SLIDESHOW_CLOCKWIPE_HXX
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a clockWiseTwelve clock wipe:
+class ClockWipe : public ParametricPolyPolygon
+{
+public:
+ /// 0,1 to 1,1 to 1,0 to 0,-1 to -1,0 to 0,1:
+ static ::basegfx::B2DPolygon calcCenteredClock( double t, double e = 1.0 );
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_CLOCKWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/combtransition.cxx b/slideshow/source/engine/transitions/combtransition.cxx
new file mode 100644
index 000000000000..3640c0961e38
--- /dev/null
+++ b/slideshow/source/engine/transitions/combtransition.cxx
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+#include <cppcanvas/spritecanvas.hxx>
+
+#include "combtransition.hxx"
+
+#include <boost/bind.hpp>
+
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+basegfx::B2DPolyPolygon createClipPolygon(
+ const ::basegfx::B2DVector& rDirection,
+ const ::basegfx::B2DSize& rSlideSize,
+ int nNumStrips, int nOffset )
+{
+ // create clip polygon in standard orientation (will later
+ // be rotated to match direction vector)
+ ::basegfx::B2DPolyPolygon aClipPoly;
+
+ // create nNumStrips/2 vertical strips
+ for( int i=nOffset; i<nNumStrips; i+=2 )
+ {
+ aClipPoly.append(
+ ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle( double(i)/nNumStrips, 0.0,
+ double(i+1)/nNumStrips, 1.0) ) );
+
+ }
+
+ // rotate polygons, such that the strips are parallel to
+ // the given direction vector
+ const ::basegfx::B2DVector aUpVec(0.0, 1.0);
+ basegfx::B2DHomMatrix aMatrix(basegfx::tools::createRotateAroundPoint(0.5, 0.5, aUpVec.angle( rDirection )));
+
+ // blow up clip polygon to slide size
+ aMatrix.scale( rSlideSize.getX(),
+ rSlideSize.getY() );
+
+ aClipPoly.transform( aMatrix );
+
+ return aClipPoly;
+}
+
+}
+
+CombTransition::CombTransition(
+ boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const ::basegfx::B2DVector& rPushDirection,
+ sal_Int32 nNumStripes )
+ : SlideChangeBase( leavingSlide, pEnteringSlide, pSoundPlayer,
+ rViewContainer, rScreenUpdater, rEventMultiplexer,
+ false /* no leaving sprite */,
+ false /* no entering sprite */ ),
+ maPushDirectionUnit( rPushDirection ),
+ mnNumStripes( nNumStripes )
+{
+}
+
+void CombTransition::renderComb( double t,
+ const ViewEntry& rViewEntry ) const
+{
+ const SlideBitmapSharedPtr& pEnteringBitmap = getEnteringBitmap(rViewEntry);
+ const cppcanvas::CanvasSharedPtr pCanvas_ = rViewEntry.mpView->getCanvas();
+
+ if( !pEnteringBitmap || !pCanvas_ )
+ return;
+
+ // calc bitmap offsets. The enter/leaving bitmaps are only
+ // as large as the actual slides. For scaled-down
+ // presentations, we have to move the left, top edge of
+ // those bitmaps to the actual position, governed by the
+ // given view transform. The aBitmapPosPixel local
+ // variable is already in device coordinate space
+ // (i.e. pixel).
+
+ // TODO(F2): Properly respect clip here. Might have to be transformed, too.
+ const basegfx::B2DHomMatrix viewTransform( rViewEntry.mpView->getTransformation() );
+ const basegfx::B2DPoint pageOrigin( viewTransform * basegfx::B2DPoint() );
+
+ // change transformation on cloned canvas to be in
+ // device pixel
+ cppcanvas::CanvasSharedPtr pCanvas( pCanvas_->clone() );
+ basegfx::B2DPoint p;
+
+ // TODO(Q2): Use basegfx bitmaps here
+ // TODO(F1): SlideBitmap is not fully portable between different canvases!
+
+ const basegfx::B2DSize enteringSizePixel(
+ getEnteringSlideSizePixel( rViewEntry.mpView) );
+
+ const basegfx::B2DVector aPushDirection = basegfx::B2DVector(
+ enteringSizePixel * maPushDirectionUnit );
+ const basegfx::B2DPolyPolygon aClipPolygon1 = basegfx::B2DPolyPolygon(
+ createClipPolygon( maPushDirectionUnit,
+ enteringSizePixel,
+ mnNumStripes, 0 ) );
+ const basegfx::B2DPolyPolygon aClipPolygon2 = basegfx::B2DPolyPolygon(
+ createClipPolygon( maPushDirectionUnit,
+ enteringSizePixel,
+ mnNumStripes, 1 ) );
+
+ SlideBitmapSharedPtr const & pLeavingBitmap = getLeavingBitmap(rViewEntry);
+ if( pLeavingBitmap )
+ {
+ // render odd strips:
+ pLeavingBitmap->clip( aClipPolygon1 );
+ // don't modify bitmap object (no move!):
+ p = basegfx::B2DPoint( pageOrigin + (t * aPushDirection) );
+ pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
+ pLeavingBitmap->draw( pCanvas );
+
+ // render even strips:
+ pLeavingBitmap->clip( aClipPolygon2 );
+ // don't modify bitmap object (no move!):
+ p = basegfx::B2DPoint( pageOrigin - (t * aPushDirection) );
+ pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
+ pLeavingBitmap->draw( pCanvas );
+ }
+
+ // TODO(Q2): Use basegfx bitmaps here
+ // TODO(F1): SlideBitmap is not fully portable between different canvases!
+
+ // render odd strips:
+ pEnteringBitmap->clip( aClipPolygon1 );
+ // don't modify bitmap object (no move!):
+ p = basegfx::B2DPoint( pageOrigin + ((t - 1.0) * aPushDirection) );
+ pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
+ pEnteringBitmap->draw( pCanvas );
+
+ // render even strips:
+ pEnteringBitmap->clip( aClipPolygon2 );
+ // don't modify bitmap object (no move!):
+ p = basegfx::B2DPoint( pageOrigin + ((1.0 - t) * aPushDirection) );
+ pCanvas->setTransformation(basegfx::tools::createTranslateB2DHomMatrix(p.getX(), p.getY()));
+ pEnteringBitmap->draw( pCanvas );
+}
+
+bool CombTransition::operator()( double t )
+{
+ std::for_each( beginViews(),
+ endViews(),
+ boost::bind( &CombTransition::renderComb,
+ this,
+ t,
+ _1 ));
+
+ getScreenUpdater().notifyUpdate();
+
+ return true;
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/combtransition.hxx b/slideshow/source/engine/transitions/combtransition.hxx
new file mode 100644
index 000000000000..e3c594763068
--- /dev/null
+++ b/slideshow/source/engine/transitions/combtransition.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_COMBTRANSITION_HXX
+#define INCLUDED_SLIDESHOW_COMBTRANSITION_HXX
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include "slidechangebase.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** Comb transition class.
+
+ This class provides a SlideChangeAnimation, showing a
+ comb-like effect (stripes of alternating push effects).
+*/
+class CombTransition : public SlideChangeBase
+{
+public:
+ /** Create the comb transition effect.
+
+ @param nNumStripes
+ Number of comb-like stripes to show in this effect
+ */
+ CombTransition( ::boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const ::basegfx::B2DVector& rPushDirection,
+ sal_Int32 nNumStripes );
+
+ // NumberAnimation
+ virtual bool operator()( double x );
+
+private:
+ const ::basegfx::B2DVector maPushDirectionUnit;
+ sal_Int32 mnNumStripes;
+
+ void renderComb( double t, const ViewEntry& rViewEntry ) const;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_COMBTRANSITION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/doublediamondwipe.cxx b/slideshow/source/engine/transitions/doublediamondwipe.cxx
new file mode 100644
index 000000000000..30ea4cdaf2d5
--- /dev/null
+++ b/slideshow/source/engine/transitions/doublediamondwipe.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include "doublediamondwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon DoubleDiamondWipe::operator () ( double t )
+{
+ // outer:
+ const double a = ::basegfx::pruneScaleValue( 0.25 + (t * 0.75) );
+ ::basegfx::B2DPolygon poly;
+ poly.append( ::basegfx::B2DPoint( 0.5 + a, 0.5 ) );
+ poly.append( ::basegfx::B2DPoint( 0.5, 0.5 - a ) );
+ poly.append( ::basegfx::B2DPoint( 0.5 - a, 0.5 ) );
+ poly.append( ::basegfx::B2DPoint( 0.5, 0.5 + a ) );
+ poly.setClosed(true);
+ ::basegfx::B2DPolyPolygon res(poly);
+
+ // inner (reverse order to clip):
+ const double b = ::basegfx::pruneScaleValue( (1.0 - t) * 0.25 );
+ poly.clear();
+ poly.append( ::basegfx::B2DPoint( 0.5 + b, 0.5 ) );
+ poly.append( ::basegfx::B2DPoint( 0.5, 0.5 + b ) );
+ poly.append( ::basegfx::B2DPoint( 0.5 - b, 0.5 ) );
+ poly.append( ::basegfx::B2DPoint( 0.5, 0.5 - b ) );
+ poly.setClosed(true);
+ res.append(poly);
+
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/doublediamondwipe.hxx b/slideshow/source/engine/transitions/doublediamondwipe.hxx
new file mode 100644
index 000000000000..16f1cddd179d
--- /dev/null
+++ b/slideshow/source/engine/transitions/doublediamondwipe.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_DOUBLEDIAMONDWIPE_HXX
+#define INCLUDED_SLIDESHOW_DOUBLEDIAMONDWIPE_HXX
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a double diamond wipe:
+class DoubleDiamondWipe : public ParametricPolyPolygon
+{
+public:
+ DoubleDiamondWipe() : m_unitRect( createUnitRect() ) {}
+ virtual ::basegfx::B2DPolyPolygon operator()( double x );
+private:
+ const ::basegfx::B2DPolyPolygon m_unitRect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_DOUBLEDIAMONDWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/ellipsewipe.cxx b/slideshow/source/engine/transitions/ellipsewipe.cxx
new file mode 100644
index 000000000000..3723889d494f
--- /dev/null
+++ b/slideshow/source/engine/transitions/ellipsewipe.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include "ellipsewipe.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon EllipseWipe::operator () ( double t )
+{
+ // currently only circle:
+ ::basegfx::B2DPolygon poly(
+ ::basegfx::tools::createPolygonFromCircle(
+ ::basegfx::B2DPoint( 0.5, 0.5 ),
+ ::basegfx::pruneScaleValue( t * M_SQRT2 / 2.0 ) ) );
+ return ::basegfx::B2DPolyPolygon( poly );
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/ellipsewipe.hxx b/slideshow/source/engine/transitions/ellipsewipe.hxx
new file mode 100644
index 000000000000..a4f9701d3e00
--- /dev/null
+++ b/slideshow/source/engine/transitions/ellipsewipe.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_ELLIPSEWIPE_HXX
+#define INCLUDED_SLIDESHOW_ELLIPSEWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a iris wipe
+class EllipseWipe : public ParametricPolyPolygon
+{
+public:
+ EllipseWipe( sal_Int32 /*nTransitionSubType xxx todo */ ) {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double x );
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_ELLIPSEWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/fanwipe.cxx b/slideshow/source/engine/transitions/fanwipe.cxx
new file mode 100644
index 000000000000..d15a37e90d8d
--- /dev/null
+++ b/slideshow/source/engine/transitions/fanwipe.cxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "transitiontools.hxx"
+#include "clockwipe.hxx"
+#include "fanwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon FanWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res;
+ ::basegfx::B2DPolygon poly(
+ ClockWipe::calcCenteredClock(
+ t / ((m_center && m_single) ? 2.0 : 4.0) ) );
+
+ res.append( poly );
+ // flip on y-axis:
+ poly.transform(basegfx::tools::createScaleB2DHomMatrix(-1.0, 1.0));
+ poly.flip();
+ res.append( poly );
+
+ if (m_center)
+ {
+ res.transform(basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5));
+
+ if (! m_single)
+ res.append( flipOnXAxis(res) );
+ }
+ else
+ {
+ OSL_ASSERT( ! m_fanIn );
+ res.transform(basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 1.0, 0.5, 1.0));
+ }
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/fanwipe.hxx b/slideshow/source/engine/transitions/fanwipe.hxx
new file mode 100644
index 000000000000..955cfe9ef4eb
--- /dev/null
+++ b/slideshow/source/engine/transitions/fanwipe.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_FANWIPE_HXX
+#define INCLUDED_SLIDESHOW_FANWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a centerTop (center=true) or double fan wipe:
+class FanWipe : public ParametricPolyPolygon
+{
+public:
+ FanWipe( bool center, bool single = true, bool fanIn = false )
+ : m_center(center), m_single(single), m_fanIn(fanIn) {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ bool m_center, m_single, m_fanIn;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_FANWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/figurewipe.cxx b/slideshow/source/engine/transitions/figurewipe.cxx
new file mode 100644
index 000000000000..a98faa670b18
--- /dev/null
+++ b/slideshow/source/engine/transitions/figurewipe.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ * ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "transitiontools.hxx"
+#include "figurewipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon FigureWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res(m_figure);
+ res.transform(basegfx::tools::createScaleTranslateB2DHomMatrix(t, t, 0.5, 0.5));
+ return res;
+}
+
+FigureWipe * FigureWipe::createTriangleWipe()
+{
+ const double s60 = sin( basegfx::deg2rad(60.0) );
+ const double s30 = sin( basegfx::deg2rad(30.0) );
+ ::basegfx::B2DPolygon figure;
+ figure.append( ::basegfx::B2DPoint( 0.5 + s30, 0.5 ) );
+ figure.append( ::basegfx::B2DPoint( 0.0, -0.5 - s60 ) );
+ figure.append( ::basegfx::B2DPoint( -0.5 - s30, 0.5 ) );
+ figure.setClosed(true);
+ return new FigureWipe(figure);
+}
+
+FigureWipe * FigureWipe::createArrowHeadWipe()
+{
+ const double s60 = sin( basegfx::deg2rad(60.0) );
+ const double s30 = sin( basegfx::deg2rad(30.0) );
+ const double off = s30;
+ ::basegfx::B2DPolygon figure;
+ figure.append( ::basegfx::B2DPoint( 0.5 + s30 + off, 0.5 + off ) );
+ figure.append( ::basegfx::B2DPoint( 0.0, -0.5 - s60 ) );
+ figure.append( ::basegfx::B2DPoint( -0.5 - s30 - off, 0.5 + off ) );
+ figure.append( ::basegfx::B2DPoint( 0.0, 0.5 ) );
+ figure.setClosed(true);
+ return new FigureWipe(figure);
+}
+
+FigureWipe * FigureWipe::createPentagonWipe()
+{
+ const double s = sin( basegfx::deg2rad(18.0) );
+ const double c = cos( basegfx::deg2rad(18.0) );
+ ::basegfx::B2DPolygon figure;
+ figure.append( ::basegfx::B2DPoint( 0.5, 0.5 ) );
+ figure.append( ::basegfx::B2DPoint( 0.5 + s, 0.5 - c ) );
+ figure.append( ::basegfx::B2DPoint( 0.0, 0.5 - c - sin(basegfx::deg2rad(36.0)) ) );
+ figure.append( ::basegfx::B2DPoint( -0.5 - s, 0.5 - c ) );
+ figure.append( ::basegfx::B2DPoint( -0.5, 0.5 ) );
+ figure.setClosed(true);
+ return new FigureWipe(figure);
+}
+
+FigureWipe * FigureWipe::createHexagonWipe()
+{
+ const double s = sin( basegfx::deg2rad(30.0) );
+ const double c = cos( basegfx::deg2rad(30.0) );
+ ::basegfx::B2DPolygon figure;
+ figure.append( ::basegfx::B2DPoint( 0.5, c ) );
+ figure.append( ::basegfx::B2DPoint( 0.5 + s, 0.0 ) );
+ figure.append( ::basegfx::B2DPoint( 0.5, -c ) );
+ figure.append( ::basegfx::B2DPoint( -0.5, -c ) );
+ figure.append( ::basegfx::B2DPoint( -0.5 - s, 0.0 ) );
+ figure.append( ::basegfx::B2DPoint( -0.5, c ) );
+ figure.setClosed(true);
+ return new FigureWipe(figure);
+}
+
+FigureWipe * FigureWipe::createStarWipe( sal_Int32 nPoints )
+{
+ const double v = (M_PI / nPoints);
+ const ::basegfx::B2DPoint p_( 0.0, -M_SQRT2 );
+ ::basegfx::B2DPolygon figure;
+ for ( sal_Int32 pos = 0; pos < nPoints; ++pos ) {
+ const double w = (pos * 2.0 * M_PI / nPoints);
+ ::basegfx::B2DHomMatrix aTransform;
+ ::basegfx::B2DPoint p(p_);
+ aTransform.rotate( -w );
+ p *= aTransform;
+ figure.append(p);
+ p = p_;
+ aTransform.identity();
+ aTransform.scale( 0.5, 0.5 );
+ aTransform.rotate( -w - v );
+ p *= aTransform;
+ figure.append(p);
+ }
+ figure.setClosed(true);
+ return new FigureWipe(figure);
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/figurewipe.hxx b/slideshow/source/engine/transitions/figurewipe.hxx
new file mode 100644
index 000000000000..366492b8ebad
--- /dev/null
+++ b/slideshow/source/engine/transitions/figurewipe.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_FIGUREWIPE_HXX
+#define INCLUDED_SLIDESHOW_FIGUREWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+class FigureWipe : public ParametricPolyPolygon
+{
+public:
+ static FigureWipe * createTriangleWipe();
+ static FigureWipe * createArrowHeadWipe();
+ static FigureWipe * createStarWipe( sal_Int32 nPoints );
+ static FigureWipe * createPentagonWipe();
+ static FigureWipe * createHexagonWipe();
+
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ FigureWipe( ::basegfx::B2DPolygon const & figure ) : m_figure(figure) {}
+ const ::basegfx::B2DPolygon m_figure;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_FIGUREWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/fourboxwipe.cxx b/slideshow/source/engine/transitions/fourboxwipe.cxx
new file mode 100644
index 000000000000..015a0507e069
--- /dev/null
+++ b/slideshow/source/engine/transitions/fourboxwipe.cxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "fourboxwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon FourBoxWipe::operator () ( double t )
+{
+ ::basegfx::B2DHomMatrix aTransform;
+ const double d = ::basegfx::pruneScaleValue( t / 2.0 );
+ if (m_cornersOut)
+ {
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5);
+ aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(d, d, -0.25, -0.25)
+ * aTransform;
+ }
+ else
+ {
+ aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(d, d, -0.5, -0.5);
+ }
+
+ // top left:
+ ::basegfx::B2DPolygon square( m_unitRect );
+ square.transform( aTransform );
+ ::basegfx::B2DPolyPolygon res( square );
+ // bottom left, flip on x-axis:
+ aTransform.scale( -1.0, 1.0 );
+ ::basegfx::B2DPolygon square2( m_unitRect );
+ square2.transform( aTransform );
+ square2.flip(); // flip direction
+ res.append( square2 );
+ // bottom right, flip on y-axis:
+ aTransform.scale( 1.0, -1.0 );
+ ::basegfx::B2DPolygon square3( m_unitRect );
+ square3.transform( aTransform );
+ res.append( square3 );
+ // top right, flip on x-axis:
+ aTransform.scale( -1.0, 1.0 );
+ ::basegfx::B2DPolygon square4( m_unitRect );
+ square4.transform( aTransform );
+ square4.flip(); // flip direction
+ res.append( square4 );
+
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.5);
+ res.transform( aTransform );
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/fourboxwipe.hxx b/slideshow/source/engine/transitions/fourboxwipe.hxx
new file mode 100644
index 000000000000..2d0a066a582e
--- /dev/null
+++ b/slideshow/source/engine/transitions/fourboxwipe.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_FOURBOXWIPE_HXX
+#define INCLUDED_SLIDESHOW_FOURBOXWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+#include "basegfx/polygon/b2dpolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a 4-box wipe
+class FourBoxWipe : public ParametricPolyPolygon
+{
+public:
+ FourBoxWipe( bool cornersOut ) : m_cornersOut(cornersOut),
+ m_unitRect( createUnitRect() )
+ {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ const bool m_cornersOut;
+ const ::basegfx::B2DPolygon m_unitRect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_FOURBOXWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/iriswipe.cxx b/slideshow/source/engine/transitions/iriswipe.cxx
new file mode 100644
index 000000000000..d554e1f7e68b
--- /dev/null
+++ b/slideshow/source/engine/transitions/iriswipe.cxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "iriswipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon IrisWipe::operator () ( double t )
+{
+ const double d = ::basegfx::pruneScaleValue(t);
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5));
+ aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(d, d, 0.5, 0.5) * aTransform;
+
+ ::basegfx::B2DPolyPolygon res( m_unitRect );
+ res.transform( aTransform );
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/iriswipe.hxx b/slideshow/source/engine/transitions/iriswipe.hxx
new file mode 100644
index 000000000000..111c366075b3
--- /dev/null
+++ b/slideshow/source/engine/transitions/iriswipe.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_IRISWIPE_HXX
+#define INCLUDED_SLIDESHOW_IRISWIPE_HXX
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a iris wipe
+class IrisWipe : public ParametricPolyPolygon
+{
+public:
+ IrisWipe() : m_unitRect( createUnitRect() ) {}
+ virtual ::basegfx::B2DPolyPolygon operator()( double x );
+private:
+ const ::basegfx::B2DPolyPolygon m_unitRect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_IRISWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/makefile.mk b/slideshow/source/engine/transitions/makefile.mk
new file mode 100644
index 000000000000..a5fbd567721c
--- /dev/null
+++ b/slideshow/source/engine/transitions/makefile.mk
@@ -0,0 +1,73 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=slideshow
+TARGET=transitions
+ENABLE_EXCEPTIONS=TRUE
+PRJINC=..$/..
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Common ----------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/barwipepolypolygon.obj \
+ $(SLO)$/boxwipe.obj \
+ $(SLO)$/clippingfunctor.obj \
+ $(SLO)$/combtransition.obj \
+ $(SLO)$/fourboxwipe.obj \
+ $(SLO)$/barndoorwipe.obj \
+ $(SLO)$/iriswipe.obj \
+ $(SLO)$/veewipe.obj \
+ $(SLO)$/ellipsewipe.obj \
+ $(SLO)$/checkerboardwipe.obj \
+ $(SLO)$/randomwipe.obj \
+ $(SLO)$/waterfallwipe.obj \
+ $(SLO)$/clockwipe.obj \
+ $(SLO)$/fanwipe.obj \
+ $(SLO)$/pinwheelwipe.obj \
+ $(SLO)$/snakewipe.obj \
+ $(SLO)$/spiralwipe.obj \
+ $(SLO)$/sweepwipe.obj \
+ $(SLO)$/figurewipe.obj \
+ $(SLO)$/doublediamondwipe.obj \
+ $(SLO)$/zigzagwipe.obj \
+ $(SLO)$/parametricpolypolygonfactory.obj \
+ $(SLO)$/shapetransitionfactory.obj \
+ $(SLO)$/slidetransitionfactory.obj \
+ $(SLO)$/transitionfactorytab.obj \
+ $(SLO)$/transitiontools.obj \
+ $(SLO)$/slidechangebase.obj
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/slideshow/source/engine/transitions/parametricpolypolygon.hxx b/slideshow/source/engine/transitions/parametricpolypolygon.hxx
new file mode 100644
index 000000000000..5f6091edced9
--- /dev/null
+++ b/slideshow/source/engine/transitions/parametricpolypolygon.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_PARAMETRICPOLYPOLYGON_HXX
+#define INCLUDED_SLIDESHOW_PARAMETRICPOLYPOLYGON_HXX
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of ParametricPolyPolygon interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a parametric poly-polygon.
+
+ This interface defines a poly-polygon, whose actual shape
+ is parameterized by a floating point value. This is
+ e.g. used to generically access the various clip polygon
+ generators for transition effects.
+
+ Since for every parametric poly-polygon, there is a set of
+ variations, which can easily be generated by simple
+ transformations or change in parameter range sweep
+ direction, objects implementing this interface only
+ generate <em>one</em> prototypical instance of the
+ parametric poly-polygon. Generally speaking, the main
+ effect direction should be horizontal, it should make
+ increasingly more area visible (transition 'in'), and when
+ there is a designated direction given, that should be
+ left-to-right.
+ */
+ class ParametricPolyPolygon
+ {
+ public:
+ virtual ~ParametricPolyPolygon() {}
+
+ /** Retrieve the poly-polygon for value t.
+
+ @param t
+ Current parameter value to retrieve the corresponding
+ poly-polygon for. Permissible values for t must be in
+ the range [0,1].
+
+ @return a poly-polygon corresponding to the given
+ parameter value. The poly-polygon is interpreted as
+ living in the unit rectangle (i.e. [0,1]x[0,1]), but
+ is not necessarily constrained to completely lie in
+ this area (this very much depends on the actual effect
+ to be generated). Although, from a performance
+ perspective, it currently <em>is</em> advantageous to
+ try to keep the poly-polygon within these bounds (at
+ least if there are no hard reasons not to do so),
+ because then reversion or out transformations are
+ potentially faster to compute (see the
+ TransitionInfo::meReverseMethod member in
+ transitionfactory.cxx). Furthermore, if one of the
+ polygon modifications involve subtraction (also see
+ TransitionInfo::meReverseMethod), all generated
+ polygons should be oriented clock-wise
+ (i.e. traversing the polygon vertices with increasing
+ vertex index should generate a clock-wise movement).
+ */
+ virtual ::basegfx::B2DPolyPolygon operator()( double t ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ParametricPolyPolygon > ParametricPolyPolygonSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_PARAMETRICPOLYPOLYGON_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/parametricpolypolygonfactory.cxx b/slideshow/source/engine/transitions/parametricpolypolygonfactory.cxx
new file mode 100644
index 000000000000..8022a012c8f2
--- /dev/null
+++ b/slideshow/source/engine/transitions/parametricpolypolygonfactory.cxx
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <com/sun/star/animations/TransitionType.hpp>
+#include <com/sun/star/animations/TransitionSubType.hpp>
+
+#include "parametricpolypolygonfactory.hxx"
+#include "barwipepolypolygon.hxx"
+#include "boxwipe.hxx"
+#include "fourboxwipe.hxx"
+#include "barndoorwipe.hxx"
+#include "doublediamondwipe.hxx"
+#include "veewipe.hxx"
+#include "iriswipe.hxx"
+#include "ellipsewipe.hxx"
+#include "checkerboardwipe.hxx"
+#include "randomwipe.hxx"
+#include "waterfallwipe.hxx"
+#include "clockwipe.hxx"
+#include "fanwipe.hxx"
+#include "pinwheelwipe.hxx"
+#include "snakewipe.hxx"
+#include "spiralwipe.hxx"
+#include "sweepwipe.hxx"
+#include "figurewipe.hxx"
+#include "zigzagwipe.hxx"
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow
+{
+ namespace internal
+ {
+ ParametricPolyPolygonSharedPtr
+ ParametricPolyPolygonFactory::createClipPolyPolygon(
+ sal_Int16 nType, sal_Int16 nSubType )
+ {
+ using namespace ::com::sun::star::animations::TransitionType;
+ using namespace ::com::sun::star::animations::TransitionSubType;
+
+ switch (nType)
+ {
+ case BARWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new BarWipePolyPolygon );
+ case BLINDSWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new BarWipePolyPolygon( 6 ) );
+ case BOXWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new BoxWipe( nSubType == LEFTCENTER ||
+ nSubType == TOPCENTER ||
+ nSubType == RIGHTCENTER||
+ nSubType == BOTTOMCENTER ) );
+ case FOURBOXWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new FourBoxWipe( nSubType == CORNERSOUT ) );
+ case BARNDOORWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new BarnDoorWipe );
+ case DIAGONALWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new BarWipePolyPolygon );
+ case VEEWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new VeeWipe );
+ case IRISWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new IrisWipe );
+ case ELLIPSEWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new EllipseWipe(nSubType) );
+ case CHECKERBOARDWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new CheckerBoardWipe );
+ case RANDOMBARWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new RandomWipe( 128, true /* bars */ ) );
+ case DISSOLVE:
+ return ParametricPolyPolygonSharedPtr(
+ new RandomWipe( 16 * 16, // for now until dxcanvas is faster
+// 64 * 64 /* elements */,
+ false /* dissolve */ ) );
+ case WATERFALLWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new WaterfallWipe(
+ 128,
+ // flipOnYAxis:
+ nSubType == VERTICALRIGHT ||
+ nSubType == HORIZONTALLEFT ) );
+ case CLOCKWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new ClockWipe );
+ case FANWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new FanWipe( // center:
+ nSubType == CENTERTOP ||
+ nSubType == CENTERRIGHT ) );
+ case PINWHEELWIPE: {
+ sal_Int32 blades;
+ switch (nSubType) {
+ case ONEBLADE:
+ blades = 1;
+ break;
+ case THREEBLADE:
+ blades = 3;
+ break;
+ case FOURBLADE:
+ blades = 4;
+ break;
+ case EIGHTBLADE:
+ blades = 8;
+ break;
+ default:
+ blades = 2;
+ break;
+ }
+ return ParametricPolyPolygonSharedPtr(
+ new PinWheelWipe( blades ) );
+ }
+ case SNAKEWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new SnakeWipe(
+ // elements:
+ 64 * 64,
+ // diagonal:
+ nSubType == TOPLEFTDIAGONAL ||
+ nSubType == TOPRIGHTDIAGONAL ||
+ nSubType == BOTTOMRIGHTDIAGONAL ||
+ nSubType == BOTTOMLEFTDIAGONAL,
+ // flipOnYAxis:
+ nSubType == TOPLEFTVERTICAL ||
+ nSubType == TOPRIGHTDIAGONAL ||
+ nSubType == BOTTOMLEFTDIAGONAL
+ ) );
+ case PARALLELSNAKESWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new ParallelSnakesWipe(
+ // elements:
+ 64 * 64,
+ // diagonal:
+ nSubType == DIAGONALBOTTOMLEFTOPPOSITE ||
+ nSubType == DIAGONALTOPLEFTOPPOSITE,
+ // flipOnYAxis:
+ nSubType == VERTICALBOTTOMLEFTOPPOSITE ||
+ nSubType == HORIZONTALTOPLEFTOPPOSITE ||
+ nSubType == DIAGONALTOPLEFTOPPOSITE,
+ // opposite:
+ nSubType == VERTICALTOPLEFTOPPOSITE ||
+ nSubType == VERTICALBOTTOMLEFTOPPOSITE ||
+ nSubType == HORIZONTALTOPLEFTOPPOSITE ||
+ nSubType == HORIZONTALTOPRIGHTOPPOSITE ||
+ nSubType == DIAGONALBOTTOMLEFTOPPOSITE ||
+ nSubType == DIAGONALTOPLEFTOPPOSITE
+ ) );
+ case SPIRALWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new SpiralWipe(
+ // elements:
+ 64 * 64,
+ // flipOnYAxis:
+ nSubType == TOPLEFTCOUNTERCLOCKWISE ||
+ nSubType == TOPRIGHTCOUNTERCLOCKWISE ||
+ nSubType == BOTTOMRIGHTCOUNTERCLOCKWISE ||
+ nSubType == BOTTOMLEFTCOUNTERCLOCKWISE ) );
+ case BOXSNAKESWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new BoxSnakesWipe(
+ // elements:
+ 64 * 64,
+ // fourBox:
+ nSubType == FOURBOXVERTICAL ||
+ nSubType == FOURBOXHORIZONTAL ) );
+ case SINGLESWEEPWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new SweepWipe(
+ // center:
+ nSubType == CLOCKWISETOP ||
+ nSubType == CLOCKWISERIGHT ||
+ nSubType == CLOCKWISEBOTTOM ||
+ nSubType == CLOCKWISELEFT,
+ // single:
+ true,
+ // oppositeVertical:
+ false,
+ // flipOnYAxis:
+ nSubType == COUNTERCLOCKWISEBOTTOMLEFT ||
+ nSubType == COUNTERCLOCKWISETOPRIGHT
+ ) );
+ case DOUBLESWEEPWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new SweepWipe(
+ // center:
+ nSubType == PARALLELVERTICAL ||
+ nSubType == PARALLELDIAGONAL ||
+ nSubType == OPPOSITEVERTICAL ||
+ nSubType == OPPOSITEHORIZONTAL,
+ // single:
+ false,
+ // oppositeVertical:
+ nSubType == OPPOSITEVERTICAL ||
+ nSubType == OPPOSITEHORIZONTAL,
+ // flipOnYAxis:
+ false ) );
+ case DOUBLEFANWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ new FanWipe(
+ //center:
+ true,
+ // single:
+ false,
+ // fanIn:
+ nSubType == FANINVERTICAL ||
+ nSubType == FANINHORIZONTAL ) );
+ case TRIANGLEWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ FigureWipe::createTriangleWipe() );
+ case ARROWHEADWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ FigureWipe::createArrowHeadWipe() );
+ case PENTAGONWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ FigureWipe::createPentagonWipe() );
+ case HEXAGONWIPE:
+ return ParametricPolyPolygonSharedPtr(
+ FigureWipe::createHexagonWipe() );
+ case STARWIPE: {
+ sal_Int32 points;
+ switch (nSubType) {
+ case FIVEPOINT:
+ points = 5;
+ break;
+ case SIXPOINT:
+ points = 6;
+ break;
+ default:
+ points = 4;
+ break;
+ }
+ return ParametricPolyPolygonSharedPtr(
+ FigureWipe::createStarWipe(points) );
+ }
+ case MISCDIAGONALWIPE: {
+ switch (nSubType) {
+ case DOUBLEBARNDOOR:
+ return ParametricPolyPolygonSharedPtr(
+ new BarnDoorWipe( true /* doubled */ ) );
+ case DOUBLEDIAMOND:
+ return ParametricPolyPolygonSharedPtr(
+ new DoubleDiamondWipe );
+ }
+ break;
+ }
+ case ZIGZAGWIPE:
+ return ParametricPolyPolygonSharedPtr( new ZigZagWipe(5) );
+ case BARNZIGZAGWIPE:
+ return ParametricPolyPolygonSharedPtr( new BarnZigZagWipe(5) );
+
+ case BOWTIEWIPE:
+ case BARNVEEWIPE:
+ case EYEWIPE:
+ case ROUNDRECTWIPE:
+ case MISCSHAPEWIPE:
+ case SALOONDOORWIPE:
+ case WINDSHIELDWIPE:
+ // for now, map to barwipe transition
+ return ParametricPolyPolygonSharedPtr(
+ new BarWipePolyPolygon );
+
+ default:
+ case PUSHWIPE:
+ case SLIDEWIPE:
+ case FADE:
+ ENSURE_OR_THROW( false,
+ "createShapeClipPolyPolygonAnimation(): Transition type mismatch" );
+ }
+
+ return ParametricPolyPolygonSharedPtr();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/parametricpolypolygonfactory.hxx b/slideshow/source/engine/transitions/parametricpolypolygonfactory.hxx
new file mode 100644
index 000000000000..979c35bfb6c0
--- /dev/null
+++ b/slideshow/source/engine/transitions/parametricpolypolygonfactory.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_PARAMETRICPOLYPOLYGONFACTORY_HXX
+#define INCLUDED_SLIDESHOW_PARAMETRICPOLYPOLYGONFACTORY_HXX
+
+#include "parametricpolypolygon.hxx"
+#include <boost/noncopyable.hpp>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /* Definition of Transitionfactory class */
+
+ class ParametricPolyPolygonFactory : private boost::noncopyable
+ {
+ public:
+ static ParametricPolyPolygonSharedPtr createClipPolyPolygon( sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType );
+
+ private:
+ // static factory
+ ParametricPolyPolygonFactory();
+ ~ParametricPolyPolygonFactory();
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_PARAMETRICPOLYPOLYGONFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/pinwheelwipe.cxx b/slideshow/source/engine/transitions/pinwheelwipe.cxx
new file mode 100644
index 000000000000..78d67b23a580
--- /dev/null
+++ b/slideshow/source/engine/transitions/pinwheelwipe.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "clockwipe.hxx"
+#include "pinwheelwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon PinWheelWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolygon poly( ClockWipe::calcCenteredClock(
+ t / m_blades,
+ 2.0 /* max edge when rotating */ ) );
+ ::basegfx::B2DPolyPolygon res;
+ for ( sal_Int32 i = m_blades; i--; )
+ {
+ ::basegfx::B2DPolygon p(poly);
+ p.transform(basegfx::tools::createRotateB2DHomMatrix((i * 2.0 * M_PI) / m_blades));
+ res.append( p );
+ }
+ res.transform(basegfx::tools::createScaleTranslateB2DHomMatrix(0.5, 0.5, 0.5, 0.5));
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/pinwheelwipe.hxx b/slideshow/source/engine/transitions/pinwheelwipe.hxx
new file mode 100644
index 000000000000..ec60813e5fd2
--- /dev/null
+++ b/slideshow/source/engine/transitions/pinwheelwipe.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_PINWHEELWIPE_HXX
+#define INCLUDED_SLIDESHOW_PINWHEELWIPE_HXX
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a n-blade pinWheel wipe:
+class PinWheelWipe : public ParametricPolyPolygon
+{
+public:
+ PinWheelWipe( sal_Int32 blades ) : m_blades(blades) {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ sal_Int32 m_blades;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_PINWHEELWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/randomwipe.cxx b/slideshow/source/engine/transitions/randomwipe.cxx
new file mode 100644
index 000000000000..4fdf9fdba0db
--- /dev/null
+++ b/slideshow/source/engine/transitions/randomwipe.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "randomwipe.hxx"
+#include "tools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+RandomWipe::RandomWipe( sal_Int32 nElements, bool randomBars )
+ : m_positions( new ::basegfx::B2DPoint[ nElements ] ),
+ m_nElements( nElements ),
+ m_rect( createUnitRect() )
+{
+ ::basegfx::B2DHomMatrix aTransform;
+ if (randomBars)
+ {
+ double edge = (1.0 / nElements);
+ for ( sal_Int32 pos = nElements; pos--; )
+ m_positions[ pos ].setY( ::basegfx::pruneScaleValue( pos * edge ) );
+ aTransform.scale( 1.0, ::basegfx::pruneScaleValue(edge) );
+ }
+ else // dissolve effect
+ {
+ sal_Int32 sqrtElements = static_cast<sal_Int32>(
+ sqrt( static_cast<double>(nElements) ) );
+ double edge = (1.0 / sqrtElements);
+ for ( sal_Int32 pos = nElements; pos--; ) {
+ m_positions[ pos ] = ::basegfx::B2DPoint(
+ ::basegfx::pruneScaleValue( (pos % sqrtElements) * edge ),
+ ::basegfx::pruneScaleValue( (pos / sqrtElements) * edge ) );
+ }
+ const double pedge = ::basegfx::pruneScaleValue(edge);
+ aTransform.scale( pedge, pedge );
+ }
+ m_rect.transform( aTransform );
+
+ // mix up:
+ for ( sal_Int32 pos1 = nElements ; pos1-- ; )
+ {
+ const sal_Int32 pos2 = getRandomOrdinal(pos1+1);
+ const ::basegfx::B2DPoint point( m_positions[ pos1 ] );
+ m_positions[ pos1 ] = m_positions[ pos2 ];
+ m_positions[ pos2 ] = point;
+ }
+}
+
+::basegfx::B2DPolyPolygon RandomWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res;
+ for ( sal_Int32 pos = static_cast<sal_Int32>(t * m_nElements); pos--; )
+ {
+ ::basegfx::B2DPoint const & point = m_positions[ pos ];
+ ::basegfx::B2DPolygon poly( m_rect );
+ poly.transform(basegfx::tools::createTranslateB2DHomMatrix(point.getX(), point.getY()));
+ res.append( poly );
+ }
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/randomwipe.hxx b/slideshow/source/engine/transitions/randomwipe.hxx
new file mode 100644
index 000000000000..473310e638c9
--- /dev/null
+++ b/slideshow/source/engine/transitions/randomwipe.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_RANDOMWIPE_HXX
+#define INCLUDED_SLIDESHOW_RANDOMWIPE_HXX
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <boost/scoped_array.hpp>
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+class RandomWipe : public ParametricPolyPolygon
+{
+public:
+ RandomWipe( sal_Int32 nElements,
+ bool randomBars /* true: generates a horizontal random bar wipe,
+ false: generates a dissolve wipe */ );
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ ::boost::scoped_array< ::basegfx::B2DPoint > m_positions;
+ sal_Int32 m_nElements;
+ ::basegfx::B2DPolygon m_rect;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_RANDOMWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/shapetransitionfactory.cxx b/slideshow/source/engine/transitions/shapetransitionfactory.cxx
new file mode 100644
index 000000000000..755ef8acbca2
--- /dev/null
+++ b/slideshow/source/engine/transitions/shapetransitionfactory.cxx
@@ -0,0 +1,411 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+#include <com/sun/star/animations/TransitionType.hpp>
+#include <com/sun/star/animations/TransitionSubType.hpp>
+
+#include "transitionfactory.hxx"
+#include "transitiontools.hxx"
+#include "parametricpolypolygonfactory.hxx"
+#include "animationfactory.hxx"
+#include "clippingfunctor.hxx"
+
+#include <boost/bind.hpp>
+
+
+using namespace ::com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+/***************************************************
+ *** ***
+ *** Shape Transition Effects ***
+ *** ***
+ ***************************************************/
+
+namespace {
+
+class ClippingAnimation : public NumberAnimation
+{
+public:
+ ClippingAnimation(
+ const ParametricPolyPolygonSharedPtr& rPolygon,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const TransitionInfo& rTransitionInfo,
+ bool bDirectionForward,
+ bool bModeIn );
+
+ ~ClippingAnimation();
+
+ // Animation interface
+ // -------------------
+ virtual void prefetch( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer );
+ virtual void start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer );
+ virtual void end();
+
+ // NumberAnimation interface
+ // -----------------------
+ virtual bool operator()( double nValue );
+ virtual double getUnderlyingValue() const;
+
+private:
+ void end_();
+
+ AnimatableShapeSharedPtr mpShape;
+ ShapeAttributeLayerSharedPtr mpAttrLayer;
+ ShapeManagerSharedPtr mpShapeManager;
+ ClippingFunctor maClippingFunctor;
+ bool mbSpriteActive;
+};
+
+ClippingAnimation::ClippingAnimation(
+ const ParametricPolyPolygonSharedPtr& rPolygon,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const TransitionInfo& rTransitionInfo,
+ bool bDirectionForward,
+ bool bModeIn ) :
+ mpShape(),
+ mpAttrLayer(),
+ mpShapeManager( rShapeManager ),
+ maClippingFunctor( rPolygon,
+ rTransitionInfo,
+ bDirectionForward,
+ bModeIn ),
+ mbSpriteActive(false)
+{
+ ENSURE_OR_THROW(
+ rShapeManager,
+ "ClippingAnimation::ClippingAnimation(): Invalid ShapeManager" );
+}
+
+ClippingAnimation::~ClippingAnimation()
+{
+ try
+ {
+ end_();
+ }
+ catch (uno::Exception &)
+ {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+}
+
+void ClippingAnimation::prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& )
+{
+}
+
+void ClippingAnimation::start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer )
+{
+ OSL_ENSURE( !mpShape,
+ "ClippingAnimation::start(): Shape already set" );
+ OSL_ENSURE( !mpAttrLayer,
+ "ClippingAnimation::start(): Attribute layer already set" );
+
+ mpShape = rShape;
+ mpAttrLayer = rAttrLayer;
+
+ ENSURE_OR_THROW( rShape,
+ "ClippingAnimation::start(): Invalid shape" );
+ ENSURE_OR_THROW( rAttrLayer,
+ "ClippingAnimation::start(): Invalid attribute layer" );
+
+ mpShape = rShape;
+ mpAttrLayer = rAttrLayer;
+
+ if( !mbSpriteActive )
+ {
+ mpShapeManager->enterAnimationMode( mpShape );
+ mbSpriteActive = true;
+ }
+}
+
+void ClippingAnimation::end()
+{
+ end_();
+}
+
+void ClippingAnimation::end_()
+{
+ if( mbSpriteActive )
+ {
+ mbSpriteActive = false;
+ mpShapeManager->leaveAnimationMode( mpShape );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+ }
+}
+
+bool ClippingAnimation::operator()( double nValue )
+{
+ ENSURE_OR_RETURN_FALSE(
+ mpAttrLayer && mpShape,
+ "ClippingAnimation::operator(): Invalid ShapeAttributeLayer" );
+
+ // set new clip
+ mpAttrLayer->setClip( maClippingFunctor( nValue,
+ mpShape->getDomBounds().getRange() ) );
+
+ if( mpShape->isContentChanged() )
+ mpShapeManager->notifyShapeUpdate( mpShape );
+
+ return true;
+}
+
+double ClippingAnimation::getUnderlyingValue() const
+{
+ ENSURE_OR_THROW(
+ mpAttrLayer,
+ "ClippingAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
+
+ return 0.0; // though this should be used in concert with
+ // ActivitiesFactory::createSimpleActivity, better
+ // explicitely name our start value.
+ // Permissible range for operator() above is [0,1]
+}
+
+} // anon namespace
+
+
+AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
+ const ActivitiesFactory::CommonParameters& rParms,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ uno::Reference< animations::XTransitionFilter > const& xTransition )
+{
+ return createShapeTransition( rParms,
+ rShape,
+ rShapeManager,
+ rSlideSize,
+ xTransition,
+ xTransition->getTransition(),
+ xTransition->getSubtype() );
+}
+
+AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
+ const ActivitiesFactory::CommonParameters& rParms,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XTransitionFilter > const& xTransition,
+ sal_Int16 nType,
+ sal_Int16 nSubType )
+{
+ ENSURE_OR_THROW(
+ xTransition.is(),
+ "TransitionFactory::createShapeTransition(): Invalid XTransition" );
+
+ const TransitionInfo* pTransitionInfo(
+ getTransitionInfo( nType, nSubType ) );
+
+ AnimationActivitySharedPtr pGeneratedActivity;
+ if( pTransitionInfo != NULL )
+ {
+ switch( pTransitionInfo->meTransitionClass )
+ {
+ default:
+ case TransitionInfo::TRANSITION_INVALID:
+ OSL_ENSURE( false,
+ "TransitionFactory::createShapeTransition(): Invalid transition type. "
+ "Don't ask me for a 0 TransitionType, have no XTransitionFilter node instead!" );
+ return AnimationActivitySharedPtr();
+
+
+ case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
+ {
+ // generate parametric poly-polygon
+ ParametricPolyPolygonSharedPtr pPoly(
+ ParametricPolyPolygonFactory::createClipPolyPolygon(
+ nType, nSubType ) );
+
+ // create a clip activity from that
+ pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
+ rParms,
+ NumberAnimationSharedPtr(
+ new ClippingAnimation(
+ pPoly,
+ rShapeManager,
+ *pTransitionInfo,
+ xTransition->getDirection(),
+ xTransition->getMode() ) ),
+ true );
+ }
+ break;
+
+ case TransitionInfo::TRANSITION_SPECIAL:
+ {
+ switch( nType )
+ {
+ case animations::TransitionType::RANDOM:
+ {
+ // select randomly one of the effects from the
+ // TransitionFactoryTable
+
+ const TransitionInfo* pRandomTransitionInfo( getRandomTransitionInfo() );
+
+ ENSURE_OR_THROW( pRandomTransitionInfo != NULL,
+ "TransitionFactory::createShapeTransition(): Got invalid random transition info" );
+
+ ENSURE_OR_THROW( pRandomTransitionInfo->mnTransitionType != animations::TransitionType::RANDOM,
+ "TransitionFactory::createShapeTransition(): Got random again for random input!" );
+
+ // and recurse
+ pGeneratedActivity = createShapeTransition( rParms,
+ rShape,
+ rShapeManager,
+ rSlideSize,
+ xTransition,
+ pRandomTransitionInfo->mnTransitionType,
+ pRandomTransitionInfo->mnTransitionSubType );
+ }
+ break;
+
+ // TODO(F3): Implement slidewipe for shape
+ case animations::TransitionType::SLIDEWIPE:
+ {
+ sal_Int16 nBarWipeSubType(0);
+ bool bDirectionForward(true);
+
+ // map slidewipe to BARWIPE, for now
+ switch( nSubType )
+ {
+ case animations::TransitionSubType::FROMLEFT:
+ nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
+ bDirectionForward = true;
+ break;
+
+ case animations::TransitionSubType::FROMRIGHT:
+ nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
+ bDirectionForward = false;
+ break;
+
+ case animations::TransitionSubType::FROMTOP:
+ nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
+ bDirectionForward = true;
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOM:
+ nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
+ bDirectionForward = false;
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "TransitionFactory::createShapeTransition(): Unexpected subtype for SLIDEWIPE" );
+ break;
+ }
+
+ // generate parametric poly-polygon
+ ParametricPolyPolygonSharedPtr pPoly(
+ ParametricPolyPolygonFactory::createClipPolyPolygon(
+ animations::TransitionType::BARWIPE,
+ nBarWipeSubType ) );
+
+ // create a clip activity from that
+ pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
+ rParms,
+ NumberAnimationSharedPtr(
+ new ClippingAnimation(
+ pPoly,
+ rShapeManager,
+ *getTransitionInfo( animations::TransitionType::BARWIPE,
+ nBarWipeSubType ),
+ bDirectionForward,
+ xTransition->getMode() ) ),
+ true );
+ }
+ break;
+
+ default:
+ {
+ // TODO(F1): Check whether there's anything left, anyway,
+ // for _shape_ transitions. AFAIK, there are no special
+ // effects for shapes...
+
+ // for now, map all to fade effect
+ pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
+ rParms,
+ AnimationFactory::createNumberPropertyAnimation(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM("Opacity") ),
+ rShape,
+ rShapeManager,
+ rSlideSize ),
+ xTransition->getMode() );
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if( !pGeneratedActivity )
+ {
+ // No animation generated, maybe no table entry for given
+ // transition?
+ OSL_TRACE(
+ "TransitionFactory::createShapeTransition(): Unknown type/subtype (%d/%d) "
+ "combination encountered",
+ xTransition->getTransition(),
+ xTransition->getSubtype() );
+ OSL_ENSURE(
+ false,
+ "TransitionFactory::createShapeTransition(): Unknown type/subtype "
+ "combination encountered" );
+ }
+
+ return pGeneratedActivity;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/slidechangebase.cxx b/slideshow/source/engine/transitions/slidechangebase.cxx
new file mode 100644
index 000000000000..eeef5d9efbdc
--- /dev/null
+++ b/slideshow/source/engine/transitions/slidechangebase.cxx
@@ -0,0 +1,538 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <canvas/canvastools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include "slidechangebase.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+#include <algorithm>
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+SlideChangeBase::SlideChangeBase( boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ bool bCreateLeavingSprites,
+ bool bCreateEnteringSprites ) :
+ mpSoundPlayer( pSoundPlayer ),
+ mrEventMultiplexer(rEventMultiplexer),
+ mrScreenUpdater(rScreenUpdater),
+ maLeavingSlide( leavingSlide ),
+ mpEnteringSlide( pEnteringSlide ),
+ maViewData(),
+ mrViewContainer(rViewContainer),
+ mbCreateLeavingSprites(bCreateLeavingSprites),
+ mbCreateEnteringSprites(bCreateEnteringSprites),
+ mbSpritesVisible(false),
+ mbFinished(false),
+ mbPrefetched(false)
+{
+ ENSURE_OR_THROW(
+ pEnteringSlide,
+ "SlideChangeBase::SlideChangeBase(): Invalid entering slide!" );
+}
+
+SlideBitmapSharedPtr SlideChangeBase::getLeavingBitmap( const ViewEntry& rViewEntry ) const
+{
+ if( !rViewEntry.mpLeavingBitmap )
+ rViewEntry.mpLeavingBitmap = createBitmap(rViewEntry.mpView,
+ maLeavingSlide);
+
+ return rViewEntry.mpLeavingBitmap;
+}
+
+SlideBitmapSharedPtr SlideChangeBase::getEnteringBitmap( const ViewEntry& rViewEntry ) const
+{
+ if( !rViewEntry.mpEnteringBitmap )
+ rViewEntry.mpEnteringBitmap = createBitmap( rViewEntry.mpView,
+ boost::optional<SlideSharedPtr>(mpEnteringSlide) );
+
+ return rViewEntry.mpEnteringBitmap;
+}
+
+SlideBitmapSharedPtr SlideChangeBase::createBitmap( const UnoViewSharedPtr& rView,
+ const boost::optional<SlideSharedPtr>& rSlide ) const
+{
+ SlideBitmapSharedPtr pRet;
+ if( !rSlide )
+ return pRet;
+
+ SlideSharedPtr const & pSlide = *rSlide;
+ if( !pSlide )
+ {
+ // TODO(P3): No need to generate a bitmap here. This only made
+ // the code more uniform. Faster would be to simply clear the
+ // sprite to black.
+
+ // create empty, black-filled bitmap
+ const basegfx::B2ISize slideSizePixel(
+ getSlideSizePixel( mpEnteringSlide->getSlideSize(),
+ rView ));
+
+ cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
+
+ // create a bitmap of appropriate size
+ cppcanvas::BitmapSharedPtr pBitmap(
+ cppcanvas::BaseGfxFactory::getInstance().createBitmap(
+ pCanvas,
+ slideSizePixel ) );
+
+ ENSURE_OR_THROW(
+ pBitmap,
+ "SlideChangeBase::createBitmap(): Cannot create page bitmap" );
+
+ cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas(
+ pBitmap->getBitmapCanvas() );
+
+ ENSURE_OR_THROW( pBitmapCanvas,
+ "SlideChangeBase::createBitmap(): "
+ "Cannot create page bitmap canvas" );
+
+ // set transformation to identitiy (->device pixel)
+ pBitmapCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // clear bitmap to black
+ fillRect( pBitmapCanvas,
+ ::basegfx::B2DRectangle( 0.0, 0.0,
+ slideSizePixel.getX(),
+ slideSizePixel.getY() ),
+ 0x000000FFU );
+
+ pRet.reset( new SlideBitmap( pBitmap ));
+ }
+ else
+ {
+ pRet = pSlide->getCurrentSlideBitmap( rView );
+ }
+
+ return pRet;
+}
+
+::basegfx::B2ISize SlideChangeBase::getEnteringSlideSizePixel( const UnoViewSharedPtr& pView ) const
+{
+ return getSlideSizePixel( mpEnteringSlide->getSlideSize(),
+ pView );
+}
+
+::basegfx::B2ISize SlideChangeBase::getLeavingSlideSizePixel( const UnoViewSharedPtr& pView ) const
+{
+ return getSlideSizePixel( (*maLeavingSlide)->getSlideSize(),
+ pView );
+}
+
+
+void SlideChangeBase::renderBitmap(
+ SlideBitmapSharedPtr const & pSlideBitmap,
+ cppcanvas::CanvasSharedPtr const & pCanvas )
+{
+ if( pSlideBitmap && pCanvas )
+ {
+ // need to render without any transformation (we
+ // assume device units):
+ const basegfx::B2DHomMatrix viewTransform(
+ pCanvas->getTransformation() );
+ const basegfx::B2DPoint pageOrigin(
+ viewTransform * basegfx::B2DPoint() );
+ const cppcanvas::CanvasSharedPtr pDevicePixelCanvas(
+ pCanvas->clone() );
+
+ // render at output position, don't modify bitmap object (no move!):
+ const basegfx::B2DHomMatrix transform(basegfx::tools::createTranslateB2DHomMatrix(
+ pageOrigin.getX(), pageOrigin.getY()));
+
+ pDevicePixelCanvas->setTransformation( transform );
+ pSlideBitmap->draw( pDevicePixelCanvas );
+ }
+}
+
+void SlideChangeBase::prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& )
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished || mbPrefetched )
+ return;
+
+ // register ourselves for view change events
+ mrEventMultiplexer.addViewHandler( shared_from_this() );
+
+ // init views and create slide bitmaps
+ std::for_each( mrViewContainer.begin(),
+ mrViewContainer.end(),
+ boost::bind( &SlideChangeBase::viewAdded,
+ this,
+ _1 ));
+
+ mbPrefetched = true;
+}
+
+void SlideChangeBase::start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rLayer )
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished )
+ return;
+
+ prefetch(rShape,rLayer); // no-op, if already done
+
+ // start accompanying sound effect, if any
+ if( mpSoundPlayer )
+ {
+ mpSoundPlayer->startPlayback();
+ // xxx todo: for now, presentation.cxx takes care about the slide
+ // #i50492# transition sound object, so just release it here
+ mpSoundPlayer.reset();
+ }
+}
+
+void SlideChangeBase::end()
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished )
+ return;
+
+ try
+ {
+ // draw fully entered bitmap:
+ ViewsVecT::const_iterator aCurr( beginViews() );
+ const ViewsVecT::const_iterator aEnd( endViews() );
+ while( aCurr != aEnd )
+ {
+ // fully clear view content to background color
+ aCurr->mpView->clearAll();
+
+ const SlideBitmapSharedPtr pSlideBitmap( getEnteringBitmap( *aCurr ));
+ pSlideBitmap->clip( basegfx::B2DPolyPolygon() /* no clipping */ );
+ renderBitmap( pSlideBitmap,
+ aCurr->mpView->getCanvas() );
+
+ ++aCurr;
+ }
+ }
+ catch( uno::Exception& )
+ {
+ // make sure releasing below happens
+ }
+
+ // swap changes to screen
+ mrScreenUpdater.notifyUpdate();
+
+ // make object dysfunctional
+ mbFinished = true;
+ ViewsVecT().swap(maViewData);
+ maLeavingSlide.reset();
+ mpEnteringSlide.reset();
+
+ // sprites have been binned above
+ mbSpritesVisible = false;
+
+ // remove also from event multiplexer, we're dead anyway
+ mrEventMultiplexer.removeViewHandler( shared_from_this() );
+}
+
+bool SlideChangeBase::operator()( double nValue )
+{
+ if( mbFinished )
+ return false;
+
+ const std::size_t nEntries( maViewData.size() );
+ bool bSpritesVisible( mbSpritesVisible );
+
+ for( ::std::size_t i=0; i<nEntries; ++i )
+ {
+ // calc sprite offsets. The enter/leaving bitmaps are only
+ // as large as the actual slides. For scaled-down
+ // presentations, we have to move the left, top edge of
+ // those bitmaps to the actual position, governed by the
+ // given view transform. The aSpritePosPixel local
+ // variable is already in device coordinate space
+ // (i.e. pixel).
+
+ ViewEntry& rViewEntry( maViewData[i] );
+ const ::cppcanvas::CanvasSharedPtr& rCanvas( rViewEntry.mpView->getCanvas() );
+ ::cppcanvas::CustomSpriteSharedPtr& rInSprite( rViewEntry.mpInSprite );
+ ::cppcanvas::CustomSpriteSharedPtr& rOutSprite( rViewEntry.mpOutSprite );
+
+ // TODO(F2): Properly respect clip here.
+
+ // Might have to be transformed, too.
+ const ::basegfx::B2DHomMatrix aViewTransform(
+ rViewEntry.mpView->getTransformation() );
+ const ::basegfx::B2DPoint aSpritePosPixel(
+ aViewTransform * ::basegfx::B2DPoint() );
+
+ // move sprite to final output position, in
+ // device coordinates
+ if( rOutSprite )
+ rOutSprite->movePixel( aSpritePosPixel );
+ if( rInSprite )
+ rInSprite->movePixel( aSpritePosPixel );
+
+ if( !mbSpritesVisible )
+ {
+ if( rOutSprite )
+ {
+ // only render once: clipping is done
+ // exclusively with the sprite
+ const ::cppcanvas::CanvasSharedPtr pOutContentCanvas(
+ rOutSprite->getContentCanvas() );
+ if( pOutContentCanvas)
+ {
+ // TODO(Q2): Use basegfx bitmaps here
+
+ // TODO(F1): SlideBitmap is not fully portable
+ // between different canvases!
+
+ // render the content
+ OSL_ASSERT( getLeavingBitmap( rViewEntry ) );
+ if( getLeavingBitmap( rViewEntry ) )
+ getLeavingBitmap( rViewEntry )->draw( pOutContentCanvas );
+ }
+ }
+
+ if( rInSprite )
+ {
+ // only render once: clipping is done
+ // exclusively with the sprite
+ const ::cppcanvas::CanvasSharedPtr pInContentCanvas(
+ rInSprite->getContentCanvas() );
+ if( pInContentCanvas )
+ {
+ // TODO(Q2): Use basegfx bitmaps here
+
+ // TODO(F1): SlideBitmap is not fully portable
+ // between different canvases!
+
+ // render the content
+ getEnteringBitmap( rViewEntry )->draw( pInContentCanvas );
+ }
+ }
+ }
+
+ if( rOutSprite )
+ performOut( rOutSprite, rViewEntry, rCanvas, nValue );
+ if( rInSprite )
+ performIn( rInSprite, rViewEntry, rCanvas, nValue );
+
+ // finishing deeds for first run.
+ if( !mbSpritesVisible)
+ {
+ // enable sprites:
+ if( rOutSprite )
+ rOutSprite->show();
+ if( rInSprite )
+ rInSprite->show();
+ bSpritesVisible = true;
+ }
+ } // for_each( sprite )
+
+ mbSpritesVisible = bSpritesVisible;
+ mrScreenUpdater.notifyUpdate();
+
+ return true;
+}
+
+void SlideChangeBase::performIn(
+ const cppcanvas::CustomSpriteSharedPtr& /*rSprite*/,
+ const ViewEntry& /*rViewEntry*/,
+ const cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
+ double /*t*/ )
+{
+}
+
+void SlideChangeBase::performOut(
+ const cppcanvas::CustomSpriteSharedPtr& /*rSprite*/,
+ const ViewEntry& /*rViewEntry*/,
+ const cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
+ double /*t*/ )
+{
+}
+
+double SlideChangeBase::getUnderlyingValue() const
+{
+ return 0.0; // though this should be used in concert with
+ // ActivitiesFactory::createSimpleActivity, better
+ // explicitely name our start value.
+ // Permissible range for operator() above is [0,1]
+}
+
+void SlideChangeBase::viewAdded( const UnoViewSharedPtr& rView )
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished )
+ return;
+
+ maViewData.push_back( ViewEntry(rView) );
+
+ ViewEntry& rEntry( maViewData.back() );
+ getEnteringBitmap( rEntry );
+ getLeavingBitmap( rEntry );
+ addSprites( rEntry );
+}
+
+void SlideChangeBase::viewRemoved( const UnoViewSharedPtr& rView )
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished )
+ return;
+
+ // erase corresponding entry from maViewData
+ maViewData.erase(
+ std::remove_if(
+ maViewData.begin(),
+ maViewData.end(),
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind( &ViewEntry::getView, _1 ))),
+ maViewData.end() );
+}
+
+void SlideChangeBase::viewChanged( const UnoViewSharedPtr& rView )
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished )
+ return;
+
+ // find entry corresponding to modified view
+ ViewsVecT::iterator aModifiedEntry(
+ std::find_if(
+ maViewData.begin(),
+ maViewData.end(),
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind( &ViewEntry::getView, _1 ) )));
+
+ OSL_ASSERT( aModifiedEntry != maViewData.end() );
+ if( aModifiedEntry == maViewData.end() )
+ return;
+
+ // clear stale info (both bitmaps and sprites prolly need a
+ // resize)
+ clearViewEntry( *aModifiedEntry );
+ addSprites( *aModifiedEntry );
+}
+
+void SlideChangeBase::viewsChanged()
+{
+ // we're a one-shot activity, and already finished
+ if( mbFinished )
+ return;
+
+ ViewsVecT::iterator aIter( maViewData.begin() );
+ ViewsVecT::iterator const aEnd ( maViewData.end() );
+ while( aIter != aEnd )
+ {
+ // clear stale info (both bitmaps and sprites prolly need a
+ // resize)
+ clearViewEntry( *aIter );
+ addSprites( *aIter );
+
+ ++aIter;
+ }
+}
+
+cppcanvas::CustomSpriteSharedPtr SlideChangeBase::createSprite(
+ UnoViewSharedPtr const & pView,
+ basegfx::B2DSize const & rSpriteSize,
+ double nPrio ) const
+{
+ // TODO(P2): change to bitmapsprite once that's working
+ const cppcanvas::CustomSpriteSharedPtr pSprite(
+ pView->createSprite( rSpriteSize,
+ nPrio ));
+
+ // alpha default is 0.0, which seems to be
+ // a bad idea when viewing content...
+ pSprite->setAlpha( 1.0 );
+ if (mbSpritesVisible)
+ pSprite->show();
+
+ return pSprite;
+}
+
+void SlideChangeBase::addSprites( ViewEntry& rEntry )
+{
+ if( mbCreateLeavingSprites && maLeavingSlide )
+ {
+ // create leaving sprite:
+ const basegfx::B2ISize leavingSlideSizePixel(
+ getLeavingBitmap( rEntry )->getSize() );
+
+ rEntry.mpOutSprite = createSprite( rEntry.mpView,
+ leavingSlideSizePixel,
+ 100 );
+ }
+
+ if( mbCreateEnteringSprites )
+ {
+ // create entering sprite:
+ const basegfx::B2ISize enteringSlideSizePixel(
+ getSlideSizePixel( mpEnteringSlide->getSlideSize(),
+ rEntry.mpView ));
+
+ rEntry.mpInSprite = createSprite( rEntry.mpView,
+ enteringSlideSizePixel,
+ 101 );
+ }
+}
+
+void SlideChangeBase::clearViewEntry( ViewEntry& rEntry )
+{
+ // clear stale info (both bitmaps and sprites prolly need a
+ // resize)
+ rEntry.mpEnteringBitmap.reset();
+ rEntry.mpLeavingBitmap.reset();
+ rEntry.mpInSprite.reset();
+ rEntry.mpOutSprite.reset();
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/slidechangebase.hxx b/slideshow/source/engine/transitions/slidechangebase.hxx
new file mode 100644
index 000000000000..bed8630e5327
--- /dev/null
+++ b/slideshow/source/engine/transitions/slidechangebase.hxx
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_TRANSITIONS_SLIDECHANGEBASE_HXX
+#define INCLUDED_SLIDESHOW_TRANSITIONS_SLIDECHANGEBASE_HXX
+
+#include <osl/mutex.hxx>
+
+#include "unoview.hxx"
+#include "vieweventhandler.hxx"
+#include "numberanimation.hxx"
+#include "slide.hxx"
+#include "screenupdater.hxx"
+#include "soundplayer.hxx"
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/optional.hpp>
+
+namespace cppcanvas
+{
+ class Canvas;
+ class CustomSprite;
+}
+
+namespace slideshow {
+namespace internal {
+
+/** Base class for all slide change effects.
+
+ This class provides the basic sprite and view handling
+ functionality. Derived classes should normally only need to
+ implement the perform() method.
+*/
+class SlideChangeBase : public ViewEventHandler,
+ public NumberAnimation,
+ public boost::enable_shared_from_this<SlideChangeBase>,
+ private ::boost::noncopyable
+{
+public:
+ // NumberAnimation
+ virtual bool operator()( double x );
+ virtual double getUnderlyingValue() const;
+
+ // Animation
+ virtual void prefetch( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& );
+ virtual void start( const AnimatableShapeSharedPtr&,
+ const ShapeAttributeLayerSharedPtr& );
+ virtual void end();
+
+ // ViewEventHandler
+ virtual void viewAdded( const UnoViewSharedPtr& rView );
+ virtual void viewRemoved( const UnoViewSharedPtr& rView );
+ virtual void viewChanged( const UnoViewSharedPtr& rView );
+ virtual void viewsChanged();
+
+protected:
+ /** Create a new SlideChanger, for the given leaving and
+ entering slides.
+ */
+ SlideChangeBase(
+ ::boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ bool bCreateLeavingSprites = true,
+ bool bCreateEnteringSprites = true );
+
+ /// Info on a per-view basis
+ struct ViewEntry
+ {
+ ViewEntry() {}
+
+ explicit ViewEntry( const UnoViewSharedPtr& rView ) :
+ mpView( rView )
+ {
+ }
+
+ /// The view this entry is for
+ UnoViewSharedPtr mpView;
+ /// outgoing slide sprite
+ boost::shared_ptr<cppcanvas::CustomSprite> mpOutSprite;
+ /// incoming slide sprite
+ boost::shared_ptr<cppcanvas::CustomSprite> mpInSprite;
+ /// outgoing slide bitmap
+ mutable SlideBitmapSharedPtr mpLeavingBitmap;
+ /// incoming slide bitmap
+ mutable SlideBitmapSharedPtr mpEnteringBitmap;
+
+ // for algo access
+ const UnoViewSharedPtr& getView() const { return mpView; }
+ };
+
+ typedef ::std::vector<ViewEntry> ViewsVecT;
+
+ ViewsVecT::const_iterator beginViews() { return maViewData.begin(); }
+ ViewsVecT::const_iterator endViews() { return maViewData.end(); }
+
+ SlideBitmapSharedPtr getLeavingBitmap( const ViewEntry& rViewEntry ) const;
+ SlideBitmapSharedPtr getEnteringBitmap( const ViewEntry& rViewEntry ) const;
+
+ SlideBitmapSharedPtr createBitmap( const UnoViewSharedPtr& pView,
+ const boost::optional<SlideSharedPtr>& rSlide_ ) const;
+
+ ::basegfx::B2ISize getEnteringSlideSizePixel( const UnoViewSharedPtr& pView ) const;
+ ::basegfx::B2ISize getLeavingSlideSizePixel( const UnoViewSharedPtr& pView ) const;
+
+ void renderBitmap( SlideBitmapSharedPtr const& pSlideBitmap,
+ boost::shared_ptr<cppcanvas::Canvas> const& pCanvas );
+
+ /** Called on derived classes to implement actual slide change.
+
+ This method is called with the sprite of the slide coming 'in'
+
+ @param rSprite
+ Current sprite to operate on. This is the sprite of the
+ 'entering' slide
+
+ @param t
+ Current parameter value
+ */
+ virtual void performIn(
+ const boost::shared_ptr<cppcanvas::CustomSprite>& rSprite,
+ const ViewEntry& rViewEntry,
+ const boost::shared_ptr<cppcanvas::Canvas>& rDestinationCanvas,
+ double t );
+
+ /** Called on derived classes to implement actual slide change.
+
+ This method is called with the sprite of the slide moving 'out'
+
+ @param rSprite
+ Current sprite to operate on. This is the sprite of the
+ 'leaving' slide
+
+ @param t
+ Current parameter value
+ */
+ virtual void performOut(
+ const boost::shared_ptr<cppcanvas::CustomSprite>& rSprite,
+ const ViewEntry& rViewEntry,
+ const boost::shared_ptr<cppcanvas::Canvas>& rDestinationCanvas,
+ double t );
+
+ ScreenUpdater& getScreenUpdater() const { return mrScreenUpdater; }
+
+private:
+
+ boost::shared_ptr<cppcanvas::CustomSprite> createSprite(
+ UnoViewSharedPtr const & pView,
+ ::basegfx::B2DSize const & rSpriteSize,
+ double nPrio ) const;
+
+ void addSprites( ViewEntry& rEntry );
+ void clearViewEntry( ViewEntry& rEntry );
+
+ ViewsVecT::iterator lookupView( UnoViewSharedPtr const & pView );
+ ViewsVecT::const_iterator lookupView( UnoViewSharedPtr const & pView ) const;
+
+ SoundPlayerSharedPtr mpSoundPlayer;
+
+ EventMultiplexer& mrEventMultiplexer;
+ ScreenUpdater& mrScreenUpdater;
+
+ ::boost::optional<SlideSharedPtr> maLeavingSlide;
+ SlideSharedPtr mpEnteringSlide;
+
+ ViewsVecT maViewData;
+ const UnoViewContainer& mrViewContainer;
+
+ const bool mbCreateLeavingSprites;
+ const bool mbCreateEnteringSprites;
+ bool mbSpritesVisible;
+ bool mbFinished;
+ bool mbPrefetched;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_TRANSITIONS_SLIDECHANGEBASE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/slidetransitionfactory.cxx b/slideshow/source/engine/transitions/slidetransitionfactory.cxx
new file mode 100644
index 000000000000..0de2f471590a
--- /dev/null
+++ b/slideshow/source/engine/transitions/slidetransitionfactory.cxx
@@ -0,0 +1,1172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+#include <cppcanvas/basegfxfactory.hxx>
+
+#include <comphelper/optional.hxx>
+#include <comphelper/make_shared_from_uno.hxx>
+
+#include <com/sun/star/rendering/XIntegerBitmap.hpp>
+#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
+#include <com/sun/star/animations/TransitionType.hpp>
+#include <com/sun/star/animations/TransitionSubType.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include "slidechangebase.hxx"
+#include "transitionfactory.hxx"
+#include "transitiontools.hxx"
+#include "parametricpolypolygonfactory.hxx"
+#include "animationfactory.hxx"
+#include "clippingfunctor.hxx"
+#include "combtransition.hxx"
+#include "tools.hxx"
+
+#include <boost/bind.hpp>
+
+
+/***************************************************
+ *** ***
+ *** Slide Transition Effects ***
+ *** ***
+ ***************************************************/
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+// helper methods
+// =============================================
+
+void fillPage( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ const ::basegfx::B2DSize& rPageSizePixel,
+ const RGBColor& rFillColor )
+{
+ // need to render without any transformation (we
+ // assume rPageSizePixel to represent device units)
+ const ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas(
+ rDestinationCanvas->clone() );
+ pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
+
+ // TODO(F2): Properly respect clip here.
+ // Might have to be transformed, too.
+ const ::basegfx::B2DHomMatrix aViewTransform(
+ rDestinationCanvas->getTransformation() );
+ const ::basegfx::B2DPoint aOutputPosPixel(
+ aViewTransform * ::basegfx::B2DPoint() );
+
+ fillRect( pDevicePixelCanvas,
+ ::basegfx::B2DRectangle(
+ aOutputPosPixel.getX(),
+ aOutputPosPixel.getY(),
+ aOutputPosPixel.getX() + rPageSizePixel.getX(),
+ aOutputPosPixel.getY() + rPageSizePixel.getY() ),
+ rFillColor.getIntegerColor() );
+}
+
+class PluginSlideChange: public SlideChangeBase
+{
+ struct TransitionViewPair {
+ uno::Reference<presentation::XTransition> mxTransition;
+ UnoViewSharedPtr mpView;
+
+ TransitionViewPair( uno::Reference<presentation::XTransition> xTransition, const UnoViewSharedPtr pView )
+ {
+ mxTransition = xTransition;
+ mpView = pView;
+ }
+
+ ~TransitionViewPair()
+ {
+ mxTransition.clear();
+ mpView.reset();;
+ }
+
+ void update( double t )
+ {
+ mxTransition->update( t );
+ }
+ };
+
+public:
+ /** Create a new SlideChanger, for the given leaving and
+ entering slide bitmaps, which uses super secret OpenGL
+ stuff.
+ */
+ PluginSlideChange( sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType,
+ boost::optional<SlideSharedPtr> const& leavingSlide_,
+ const SlideSharedPtr& pEnteringSlide,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ const uno::Reference<
+ presentation::XTransitionFactory>& xFactory,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ EventMultiplexer& rEventMultiplexer) :
+ SlideChangeBase( leavingSlide_,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer ),
+ maTransitions(),
+ mbSuccess( false ),
+ mnTransitionType( nTransitionType ),
+ mnTransitionSubType( nTransitionSubType ),
+ mxFactory( xFactory )
+ {
+ // create one transition per view
+ UnoViewVector::const_iterator aCurrView (rViewContainer.begin());
+ const UnoViewVector::const_iterator aEnd(rViewContainer.end());
+ while( aCurrView != aEnd )
+ {
+ if(! addTransition( *aCurrView ) )
+ return;
+
+ ENSURE_OR_THROW(maTransitions.back() && maTransitions.back()->mxTransition.is(),
+ "Failed to create plugin transition");
+ ++aCurrView;
+ }
+ mbSuccess = true;
+ }
+
+ ~PluginSlideChange()
+ {
+ mxFactory.clear();
+
+ ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
+ ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
+ while( aCurrView != aEnd )
+ {
+ delete (*aCurrView);
+ ++aCurrView;
+ }
+ maTransitions.clear();
+ }
+
+ bool addTransition( const UnoViewSharedPtr& rView )
+ {
+ uno::Reference<presentation::XTransition> rTransition = mxFactory->createTransition(
+ mnTransitionType,
+ mnTransitionSubType,
+ rView->getUnoView(),
+ getLeavingBitmap(ViewEntry(rView))->getXBitmap(),
+ getEnteringBitmap(ViewEntry(rView))->getXBitmap() );
+
+ if( rTransition.is() )
+ maTransitions.push_back( new TransitionViewPair( rTransition, rView ) );
+ else
+ return false;
+
+ return true;
+ }
+
+ virtual bool operator()( double t )
+ {
+ std::for_each(maTransitions.begin(),
+ maTransitions.end(),
+ boost::bind( &TransitionViewPair::update,
+ _1, t) );
+ return true;
+ }
+
+ bool Success()
+ {
+ return mbSuccess;
+ }
+
+ // ViewEventHandler
+ virtual void viewAdded( const UnoViewSharedPtr& rView )
+ {
+ OSL_TRACE("PluginSlideChange viewAdded");
+ SlideChangeBase::viewAdded( rView );
+
+ ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
+ ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
+ bool bKnown = false;
+ while( aCurrView != aEnd )
+ {
+ if( (*aCurrView)->mpView == rView ) {
+ bKnown = true;
+ break;
+ }
+ ++aCurrView;
+ }
+
+ if( !bKnown ) {
+ OSL_TRACE("need to be added");
+
+ addTransition( rView );
+ }
+ }
+
+ virtual void viewRemoved( const UnoViewSharedPtr& rView )
+ {
+ OSL_TRACE("PluginSlideChange viewRemoved");
+ SlideChangeBase::viewRemoved( rView );
+
+ ::std::vector< TransitionViewPair* >::iterator aCurrView (maTransitions.begin());
+ ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
+ while( aCurrView != aEnd )
+ {
+ if( (*aCurrView)->mpView == rView ) {
+ OSL_TRACE( "view removed" );
+ delete (*aCurrView);
+ maTransitions.erase( aCurrView );
+ break;
+ }
+ ++aCurrView;
+ }
+ }
+
+ virtual void viewChanged( const UnoViewSharedPtr& rView )
+ {
+ OSL_TRACE("PluginSlideChange viewChanged");
+ SlideChangeBase::viewChanged( rView );
+
+ ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
+ ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
+ while( aCurrView != aEnd )
+ {
+ if( (*aCurrView)->mpView == rView ) {
+ OSL_TRACE( "view changed" );
+ (*aCurrView)->mxTransition->viewChanged( rView->getUnoView(),
+ getLeavingBitmap(ViewEntry(rView))->getXBitmap(),
+ getEnteringBitmap(ViewEntry(rView))->getXBitmap() );
+ } else
+ OSL_TRACE( "view did not changed" );
+
+ ++aCurrView;
+ }
+ }
+
+ virtual void viewsChanged()
+ {
+ OSL_TRACE("PluginSlideChange viewsChanged");
+ SlideChangeBase::viewsChanged();
+
+ ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
+ ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
+ while( aCurrView != aEnd )
+ {
+ OSL_TRACE( "view changed" );
+ (*aCurrView)->mxTransition->viewChanged( (*aCurrView)->mpView->getUnoView(),
+ getLeavingBitmap(ViewEntry((*aCurrView)->mpView))->getXBitmap(),
+ getEnteringBitmap(ViewEntry((*aCurrView)->mpView))->getXBitmap() );
+ ++aCurrView;
+ }
+ }
+
+private:
+ // One transition object per view
+ std::vector< TransitionViewPair* > maTransitions;
+
+ // bool
+ bool mbSuccess;
+
+ sal_Int16 mnTransitionType;
+ sal_Int16 mnTransitionSubType;
+
+ uno::Reference<presentation::XTransitionFactory> mxFactory;
+};
+
+class ClippedSlideChange : public SlideChangeBase
+{
+public:
+ /** Create a new SlideChanger, for the given leaving and
+ entering slide bitmaps, which applies the given clip
+ polygon.
+ */
+ ClippedSlideChange(
+ const SlideSharedPtr& pEnteringSlide,
+ const ParametricPolyPolygonSharedPtr& rPolygon,
+ const TransitionInfo& rTransitionInfo,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ bool bDirectionForward,
+ const SoundPlayerSharedPtr& pSoundPlayer ) :
+ SlideChangeBase(
+ // leaving bitmap is empty, we're leveraging the fact that the
+ // old slide is still displayed in the background:
+ boost::optional<SlideSharedPtr>(),
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer ),
+ maClippingFunctor( rPolygon,
+ rTransitionInfo,
+ bDirectionForward,
+ true )
+ {}
+
+ virtual void performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+ virtual void performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+private:
+ ClippingFunctor maClippingFunctor;
+};
+
+void ClippedSlideChange::performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
+ double t )
+{
+ // #i46602# Better work in device coordinate space here,
+ // otherwise, we too easily suffer from roundoffs. Apart from
+ // that, getEnteringSizePixel() _guarantees_ to cover the whole
+ // slide bitmap. There's a catch, though: this removes any effect
+ // of the view transformation (e.g. rotation) from the transition.
+ rSprite->setClipPixel(
+ maClippingFunctor( t,
+ getEnteringSlideSizePixel(rViewEntry.mpView) ) );
+}
+
+void ClippedSlideChange::performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& /*rSprite*/,
+ const ViewEntry& /*rViewEntry*/,
+ const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
+ double /*t*/ )
+{
+ // not needed here
+}
+
+
+class FadingSlideChange : public SlideChangeBase
+{
+public:
+ /** Create a new SlideChanger, for the given leaving and
+ entering slides, which applies a fade effect.
+ */
+ FadingSlideChange(
+ boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ boost::optional<RGBColor> const& rFadeColor,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer )
+ : SlideChangeBase( leavingSlide,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer ),
+ maFadeColor( rFadeColor ),
+ mbFirstTurn( true )
+ {}
+
+ virtual void performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+ virtual void performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+private:
+ const boost::optional< RGBColor > maFadeColor;
+ bool mbFirstTurn;
+};
+
+void FadingSlideChange::performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& /*rViewEntry*/,
+ const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
+ double t )
+{
+ ENSURE_OR_THROW(
+ rSprite,
+ "FadingSlideChange::performIn(): Invalid sprite" );
+
+ if( maFadeColor )
+ // After half of the active time, fade in new slide
+ rSprite->setAlpha( t > 0.5 ? 2.0*(t-0.5) : 0.0 );
+ else
+ // Fade in new slide over full active time
+ rSprite->setAlpha( t );
+}
+
+void FadingSlideChange::performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t )
+{
+ ENSURE_OR_THROW(
+ rSprite,
+ "FadingSlideChange::performOut(): Invalid sprite" );
+ ENSURE_OR_THROW(
+ rDestinationCanvas,
+ "FadingSlideChange::performOut(): Invalid dest canvas" );
+
+ // only needed for color fades
+ if( maFadeColor )
+ {
+ if( mbFirstTurn )
+ {
+ mbFirstTurn = false;
+
+ // clear page to given fade color. 'Leaving' slide is
+ // painted atop of that, but slowly fading out.
+ fillPage( rDestinationCanvas,
+ getEnteringSlideSizePixel( rViewEntry.mpView ),
+ *maFadeColor );
+ }
+
+ // Until half of the active time, fade out old
+ // slide. After half of the active time, old slide
+ // will be invisible.
+ rSprite->setAlpha( t > 0.5 ? 0.0 : 2.0*(0.5-t) );
+ }
+}
+
+class CutSlideChange : public SlideChangeBase
+{
+public:
+ /** Create a new SlideChanger, for the given leaving and
+ entering slides, which applies a cut effect.
+ */
+ CutSlideChange(
+ boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const RGBColor& rFadeColor,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer )
+ : SlideChangeBase( leavingSlide,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer ),
+ maFadeColor( rFadeColor ),
+ mbFirstTurn( true )
+ {}
+
+ virtual void performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+ virtual void performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+private:
+ RGBColor maFadeColor;
+ bool mbFirstTurn;
+};
+
+void CutSlideChange::performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& /*rViewEntry*/,
+ const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
+ double t )
+{
+ ENSURE_OR_THROW(
+ rSprite,
+ "CutSlideChange::performIn(): Invalid sprite" );
+
+ // After 2/3rd of the active time, display new slide
+ rSprite->setAlpha( t > 2/3.0 ? 1.0 : 0.0 );
+}
+
+void CutSlideChange::performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t )
+{
+ ENSURE_OR_THROW(
+ rSprite,
+ "CutSlideChange::performOut(): Invalid sprite" );
+ ENSURE_OR_THROW(
+ rDestinationCanvas,
+ "FadingSlideChange::performOut(): Invalid dest canvas" );
+
+ if( mbFirstTurn )
+ {
+ mbFirstTurn = false;
+
+ // clear page to given fade color. 'Leaving' slide is
+ // painted atop of that
+ fillPage( rDestinationCanvas,
+ getEnteringSlideSizePixel( rViewEntry.mpView ),
+ maFadeColor );
+ }
+
+ // Until 1/3rd of the active time, display old slide.
+ rSprite->setAlpha( t > 1/3.0 ? 0.0 : 1.0 );
+}
+
+class MovingSlideChange : public SlideChangeBase
+{
+ /// Direction vector for leaving slide,
+ const ::basegfx::B2DVector maLeavingDirection;
+
+ /// Direction vector for entering slide,
+ const ::basegfx::B2DVector maEnteringDirection;
+
+ bool mbFirstPerformCall;
+
+public:
+ /** Create a new SlideChanger, for the given entering slide
+ bitmaps, which performes a moving slide change effect
+
+ @param rLeavingDirection
+ Direction vector. The move is performed along this
+ direction vector, starting at a position where the leaving
+ slide is fully visible, and ending at a position where the
+ leaving slide is just not visible. The vector must have
+ unit length.
+
+ @param rEnteringDirection
+ Direction vector. The move is performed along this
+ direction vector, starting at a position where the
+ entering slide is just not visible, and ending at the
+ final slide position. The vector must have unit length.
+ */
+ MovingSlideChange(
+ const boost::optional<SlideSharedPtr>& leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const ::basegfx::B2DVector& rLeavingDirection,
+ const ::basegfx::B2DVector& rEnteringDirection )
+ : SlideChangeBase(
+ leavingSlide, pEnteringSlide, pSoundPlayer,
+ rViewContainer, rScreenUpdater, rEventMultiplexer,
+ // Optimization: when leaving bitmap is given,
+ // but it does not move, don't create sprites for it,
+ // we simply paint it once at startup:
+ !rLeavingDirection.equalZero() /* bCreateLeavingSprites */,
+ !rEnteringDirection.equalZero() /* bCreateEnteringSprites */ ),
+ // TODO(F1): calc correct length of direction
+ // vector. Directions not strictly horizontal or vertical
+ // must travel a longer distance.
+ maLeavingDirection( rLeavingDirection ),
+ // TODO(F1): calc correct length of direction
+ // vector. Directions not strictly horizontal or vertical
+ // must travel a longer distance.
+ maEnteringDirection( rEnteringDirection ),
+ mbFirstPerformCall( true )
+ {}
+
+ virtual void performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+
+ virtual void performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t );
+};
+
+void MovingSlideChange::performIn(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t )
+{
+ // intro sprite moves:
+
+ ENSURE_OR_THROW(
+ rSprite,
+ "MovingSlideChange::performIn(): Invalid sprite" );
+ ENSURE_OR_THROW(
+ rDestinationCanvas,
+ "MovingSlideChange::performIn(): Invalid dest canvas" );
+
+ if (mbFirstPerformCall && maLeavingDirection.equalZero())
+ {
+ mbFirstPerformCall = false;
+ renderBitmap( getLeavingBitmap(rViewEntry), rDestinationCanvas );
+ }
+
+ // TODO(F1): This does not account for non-translational
+ // transformations! If the canvas is rotated, we still
+ // move the sprite unrotated (which might or might not
+ // produce the intended effect).
+ const basegfx::B2DHomMatrix aViewTransform(
+ rDestinationCanvas->getTransformation() );
+ const basegfx::B2DPoint aPageOrigin(
+ aViewTransform * basegfx::B2DPoint() );
+
+ // move sprite
+ rSprite->movePixel(
+ aPageOrigin +
+ ((t - 1.0) *
+ ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) *
+ maEnteringDirection) );
+}
+
+void MovingSlideChange::performOut(
+ const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
+ const ViewEntry& rViewEntry,
+ const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
+ double t )
+{
+ // outro sprite moves:
+
+ ENSURE_OR_THROW(
+ rSprite,
+ "MovingSlideChange::performOut(): Invalid sprite" );
+ ENSURE_OR_THROW(
+ rDestinationCanvas,
+ "MovingSlideChange::performOut(): Invalid dest canvas" );
+
+ if (mbFirstPerformCall && maEnteringDirection.equalZero())
+ {
+ mbFirstPerformCall = false;
+ renderBitmap( getEnteringBitmap(rViewEntry), rDestinationCanvas );
+ }
+
+ // TODO(F1): This does not account for non-translational
+ // transformations! If the canvas is rotated, we still
+ // move the sprite unrotated (which might or might not
+ // produce the intended effect).
+ const basegfx::B2DHomMatrix aViewTransform(
+ rDestinationCanvas->getTransformation() );
+ const basegfx::B2DPoint aPageOrigin(
+ aViewTransform * basegfx::B2DPoint() );
+
+ // move sprite
+ rSprite->movePixel(
+ aPageOrigin + (t *
+ ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) *
+ maLeavingDirection) );
+}
+
+
+NumberAnimationSharedPtr createPushWipeTransition(
+ boost::optional<SlideSharedPtr> const & leavingSlide_,
+ const SlideSharedPtr& pEnteringSlide,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ sal_Int16 /*nTransitionType*/,
+ sal_Int16 nTransitionSubType,
+ bool /*bTransitionDirection*/,
+ const SoundPlayerSharedPtr& pSoundPlayer )
+{
+ boost::optional<SlideSharedPtr> leavingSlide; // no bitmap
+ if (leavingSlide_ && (*leavingSlide_).get() != 0)
+ {
+ // opt: only page, if we've an
+ // actual slide to move out here. We
+ // _don't_ need a fake black background
+ // bitmap, neither for push nor for comb
+ // wipes.
+ leavingSlide = leavingSlide_;
+ }
+
+ // setup direction vector
+ bool bComb( false );
+ ::basegfx::B2DVector aDirection;
+ switch( nTransitionSubType )
+ {
+ default:
+ OSL_ENSURE(
+ false,
+ "createPushWipeTransition(): Unexpected transition "
+ "subtype for animations::TransitionType::PUSHWIPE "
+ "transitions" );
+ return NumberAnimationSharedPtr();
+
+ case animations::TransitionSubType::FROMTOP:
+ aDirection = ::basegfx::B2DVector( 0.0, 1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOM:
+ aDirection = ::basegfx::B2DVector( 0.0, -1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMLEFT:
+ aDirection = ::basegfx::B2DVector( 1.0, 0.0 );
+ break;
+
+ case animations::TransitionSubType::FROMRIGHT:
+ aDirection = ::basegfx::B2DVector( -1.0, 0.0 );
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOMRIGHT:
+ aDirection = ::basegfx::B2DVector( -1.0, -1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOMLEFT:
+ aDirection = ::basegfx::B2DVector( 1.0, -1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMTOPRIGHT:
+ aDirection = ::basegfx::B2DVector( -1.0, 1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMTOPLEFT:
+ aDirection = ::basegfx::B2DVector( 1.0, 1.0 );
+ break;
+
+ case animations::TransitionSubType::COMBHORIZONTAL:
+ aDirection = ::basegfx::B2DVector( 1.0, 0.0 );
+ bComb = true;
+ break;
+
+ case animations::TransitionSubType::COMBVERTICAL:
+ aDirection = ::basegfx::B2DVector( 0.0, 1.0 );
+ bComb = true;
+ break;
+ }
+
+ if( bComb )
+ {
+ return NumberAnimationSharedPtr(
+ new CombTransition( leavingSlide,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ aDirection,
+ 24 /* comb with 12 stripes */ ));
+ }
+ else
+ {
+ return NumberAnimationSharedPtr(
+ new MovingSlideChange( leavingSlide,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ aDirection,
+ aDirection ));
+ }
+}
+
+NumberAnimationSharedPtr createSlideWipeTransition(
+ boost::optional<SlideSharedPtr> const & leavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ sal_Int16 /*nTransitionType*/,
+ sal_Int16 nTransitionSubType,
+ bool bTransitionDirection,
+ const SoundPlayerSharedPtr& pSoundPlayer )
+{
+ // setup 'in' direction vector
+ ::basegfx::B2DVector aInDirection;
+ switch( nTransitionSubType )
+ {
+ default:
+ OSL_ENSURE(
+ false,
+ "createSlideWipeTransition(): Unexpected transition "
+ "subtype for animations::TransitionType::SLIDEWIPE "
+ "transitions" );
+ return NumberAnimationSharedPtr();
+
+ case animations::TransitionSubType::FROMTOP:
+ aInDirection = ::basegfx::B2DVector( 0.0, 1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMRIGHT:
+ aInDirection = ::basegfx::B2DVector( -1.0, 0.0 );
+ break;
+
+ case animations::TransitionSubType::FROMLEFT:
+ aInDirection = ::basegfx::B2DVector( 1.0, 0.0 );
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOM:
+ aInDirection = ::basegfx::B2DVector( 0.0, -1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOMRIGHT:
+ aInDirection = ::basegfx::B2DVector( -1.0, -1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMBOTTOMLEFT:
+ aInDirection = ::basegfx::B2DVector( 1.0, -1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMTOPRIGHT:
+ aInDirection = ::basegfx::B2DVector( -1.0, 1.0 );
+ break;
+
+ case animations::TransitionSubType::FROMTOPLEFT:
+ aInDirection = ::basegfx::B2DVector( 1.0, 1.0 );
+ break;
+ }
+
+ if( bTransitionDirection )
+ {
+ // normal, 'forward' slide wipe effect. Since the old
+ // content is still on screen (and does not move), we omit
+ // the 'leaving' slide.
+ // =======================================================
+
+ return NumberAnimationSharedPtr(
+ new MovingSlideChange(
+ boost::optional<SlideSharedPtr>() /* no slide */,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ basegfx::B2DVector(),
+ aInDirection ));
+ }
+ else
+ {
+ // 'reversed' slide wipe effect. Reverse for slide wipes
+ // means, that the new slide is in the back, statically,
+ // and the old one is moving off in the foreground.
+ // =======================================================
+
+ return NumberAnimationSharedPtr(
+ new MovingSlideChange( leavingSlide,
+ pEnteringSlide,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ aInDirection,
+ basegfx::B2DVector() ));
+ }
+}
+
+NumberAnimationSharedPtr createPluginTransition(
+ sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType,
+ boost::optional<SlideSharedPtr> const& pLeavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ const uno::Reference<
+ presentation::XTransitionFactory>& xFactory,
+ const SoundPlayerSharedPtr& pSoundPlayer,
+ EventMultiplexer& rEventMultiplexer)
+{
+ PluginSlideChange* pTransition =
+ new PluginSlideChange(
+ nTransitionType,
+ nTransitionSubType,
+ pLeavingSlide,
+ pEnteringSlide,
+ rViewContainer,
+ rScreenUpdater,
+ xFactory,
+ pSoundPlayer,
+ rEventMultiplexer );
+
+ if( pTransition->Success() )
+ return NumberAnimationSharedPtr( pTransition );
+ else {
+ delete pTransition;
+ return NumberAnimationSharedPtr();
+ }
+}
+
+} // anon namespace
+
+
+NumberAnimationSharedPtr TransitionFactory::createSlideTransition(
+ const SlideSharedPtr& pLeavingSlide,
+ const SlideSharedPtr& pEnteringSlide,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const uno::Reference<presentation::XTransitionFactory>& xOptionalFactory,
+ sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType,
+ bool bTransitionDirection,
+ const RGBColor& rTransitionFadeColor,
+ const SoundPlayerSharedPtr& pSoundPlayer )
+{
+ // xxx todo: change to TransitionType::NONE, TransitionSubType::NONE:
+ if (nTransitionType == 0 && nTransitionSubType == 0) {
+ // just play sound, no slide transition:
+ if (pSoundPlayer) {
+ pSoundPlayer->startPlayback();
+ // xxx todo: for now, presentation.cxx takes care about the slide
+ // #i50492# transition sound object, so just release it here
+ }
+ return NumberAnimationSharedPtr();
+ }
+
+ ENSURE_OR_THROW(
+ pEnteringSlide,
+ "TransitionFactory::createSlideTransition(): Invalid entering slide" );
+
+ if( xOptionalFactory.is() &&
+ xOptionalFactory->hasTransition(nTransitionType, nTransitionSubType) )
+ {
+ // #i82460# - optional plugin factory claims this transition. delegate.
+ NumberAnimationSharedPtr pTransition(
+ createPluginTransition(
+ nTransitionType,
+ nTransitionSubType,
+ comphelper::make_optional(pLeavingSlide),
+ pEnteringSlide,
+ rViewContainer,
+ rScreenUpdater,
+ xOptionalFactory,
+ pSoundPlayer,
+ rEventMultiplexer ));
+
+ if( pTransition.get() )
+ return pTransition;
+ }
+
+ const TransitionInfo* pTransitionInfo(
+ getTransitionInfo( nTransitionType, nTransitionSubType ) );
+
+ if( pTransitionInfo != NULL )
+ {
+ switch( pTransitionInfo->meTransitionClass )
+ {
+ default:
+ case TransitionInfo::TRANSITION_INVALID:
+ OSL_TRACE(
+ "TransitionFactory::createSlideTransition(): "
+ "Invalid type/subtype (%d/%d) combination encountered.",
+ nTransitionType,
+ nTransitionSubType );
+ return NumberAnimationSharedPtr();
+
+
+ case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
+ {
+ // generate parametric poly-polygon
+ ParametricPolyPolygonSharedPtr pPoly(
+ ParametricPolyPolygonFactory::createClipPolyPolygon(
+ nTransitionType, nTransitionSubType ) );
+
+ // create a clip transition from that
+ return NumberAnimationSharedPtr(
+ new ClippedSlideChange( pEnteringSlide,
+ pPoly,
+ *pTransitionInfo,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ bTransitionDirection,
+ pSoundPlayer ));
+ }
+
+ case TransitionInfo::TRANSITION_SPECIAL:
+ {
+ switch( nTransitionType )
+ {
+ default:
+ OSL_ENSURE(
+ false,
+ "TransitionFactory::createSlideTransition(): "
+ "Unexpected transition type for "
+ "TRANSITION_SPECIAL transitions" );
+ return NumberAnimationSharedPtr();
+
+ case animations::TransitionType::RANDOM:
+ {
+ // select randomly one of the effects from the
+ // TransitionFactoryTable
+
+ const TransitionInfo* pRandomTransitionInfo(
+ getRandomTransitionInfo() );
+
+ ENSURE_OR_THROW(
+ pRandomTransitionInfo != NULL,
+ "TransitionFactory::createSlideTransition(): "
+ "Got invalid random transition info" );
+
+ ENSURE_OR_THROW(
+ pRandomTransitionInfo->mnTransitionType !=
+ animations::TransitionType::RANDOM,
+ "TransitionFactory::createSlideTransition(): "
+ "Got random again for random input!" );
+
+ // and recurse
+ return createSlideTransition(
+ pLeavingSlide,
+ pEnteringSlide,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ xOptionalFactory,
+ pRandomTransitionInfo->mnTransitionType,
+ pRandomTransitionInfo->mnTransitionSubType,
+ bTransitionDirection,
+ rTransitionFadeColor,
+ pSoundPlayer );
+ }
+
+ case animations::TransitionType::PUSHWIPE:
+ {
+ return createPushWipeTransition(
+ comphelper::make_optional(pLeavingSlide),
+ pEnteringSlide,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ nTransitionType,
+ nTransitionSubType,
+ bTransitionDirection,
+ pSoundPlayer );
+ }
+
+ case animations::TransitionType::SLIDEWIPE:
+ {
+ return createSlideWipeTransition(
+ comphelper::make_optional(pLeavingSlide),
+ pEnteringSlide,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer,
+ nTransitionType,
+ nTransitionSubType,
+ bTransitionDirection,
+ pSoundPlayer );
+ }
+
+ case animations::TransitionType::BARWIPE:
+ case animations::TransitionType::FADE:
+ {
+ // black page:
+ boost::optional<SlideSharedPtr> leavingSlide;
+
+ switch( nTransitionSubType )
+ {
+ case animations::TransitionSubType::CROSSFADE:
+ // crossfade needs no further setup,
+ // just blend new slide over existing
+ // background.
+ break;
+
+ // TODO(F1): Implement toColor/fromColor fades
+ case animations::TransitionSubType::FADETOCOLOR:
+ // FALLTHROUGH intended
+ case animations::TransitionSubType::FADEFROMCOLOR:
+ // FALLTHROUGH intended
+ case animations::TransitionSubType::FADEOVERCOLOR:
+ if (pLeavingSlide) {
+ // only generate, if fade
+ // effect really needs it.
+ leavingSlide.reset( pLeavingSlide );
+ }
+ break;
+
+ default:
+ ENSURE_OR_THROW( false,
+ "SlideTransitionFactory::createSlideTransition(): Unknown FADE subtype" );
+ }
+
+ if( nTransitionType == animations::TransitionType::FADE )
+ return NumberAnimationSharedPtr(
+ new FadingSlideChange(
+ leavingSlide,
+ pEnteringSlide,
+ comphelper::make_optional(
+ rTransitionFadeColor),
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer ));
+ else
+ return NumberAnimationSharedPtr(
+ new CutSlideChange(
+ leavingSlide,
+ pEnteringSlide,
+ rTransitionFadeColor,
+ pSoundPlayer,
+ rViewContainer,
+ rScreenUpdater,
+ rEventMultiplexer ));
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ // No animation generated, maybe no table entry for given
+ // transition?
+ OSL_TRACE(
+ "TransitionFactory::createSlideTransition(): "
+ "Unknown type/subtype (%d/%d) combination encountered",
+ nTransitionType,
+ nTransitionSubType );
+ OSL_ENSURE(
+ false,
+ "TransitionFactory::createSlideTransition(): "
+ "Unknown type/subtype combination encountered" );
+
+ return NumberAnimationSharedPtr();
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/snakewipe.cxx b/slideshow/source/engine/transitions/snakewipe.cxx
new file mode 100644
index 000000000000..86572f7f9abe
--- /dev/null
+++ b/slideshow/source/engine/transitions/snakewipe.cxx
@@ -0,0 +1,247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "snakewipe.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+SnakeWipe::SnakeWipe( sal_Int32 nElements, bool diagonal, bool flipOnYAxis )
+ : m_sqrtElements( static_cast<sal_Int32>(
+ sqrt( static_cast<double>(nElements) ) ) ),
+ m_elementEdge( 1.0 / m_sqrtElements ),
+ m_diagonal(diagonal),
+ m_flipOnYAxis(flipOnYAxis)
+{
+}
+
+::basegfx::B2DPolyPolygon SnakeWipe::calcSnake( double t ) const
+{
+ ::basegfx::B2DPolyPolygon res;
+ const double area = (t * m_sqrtElements * m_sqrtElements);
+ const sal_Int32 line_ = (static_cast<sal_Int32>(area) / m_sqrtElements);
+ const double line = ::basegfx::pruneScaleValue(
+ static_cast<double>(line_) / m_sqrtElements );
+ const double col = ::basegfx::pruneScaleValue(
+ (area - (line_ * m_sqrtElements)) / m_sqrtElements );
+
+ if (! ::basegfx::fTools::equalZero( line )) {
+ ::basegfx::B2DPolygon poly;
+ poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) );
+ poly.append( ::basegfx::B2DPoint( 0.0, line ) );
+ poly.append( ::basegfx::B2DPoint( 1.0, line ) );
+ poly.append( ::basegfx::B2DPoint( 1.0, 0.0 ) );
+ poly.setClosed(true);
+ res.append(poly);
+ }
+ if (! ::basegfx::fTools::equalZero( col ))
+ {
+ double offset = 0.0;
+ if ((line_ & 1) == 1) {
+ // odd line: => right to left
+ offset = (1.0 - col);
+ }
+ ::basegfx::B2DPolygon poly;
+ poly.append( ::basegfx::B2DPoint( offset, line ) );
+ poly.append( ::basegfx::B2DPoint( offset,
+ line + m_elementEdge ) );
+ poly.append( ::basegfx::B2DPoint( offset + col,
+ line + m_elementEdge ) );
+ poly.append( ::basegfx::B2DPoint( offset + col, line ) );
+ poly.setClosed(true);
+ res.append(poly);
+ }
+
+ return res;
+}
+
+::basegfx::B2DPolyPolygon SnakeWipe::calcHalfDiagonalSnake(
+ double t, bool in ) const
+{
+ ::basegfx::B2DPolyPolygon res;
+
+ if (in) {
+ const double sqrtArea2 = sqrt( t * m_sqrtElements * m_sqrtElements );
+ const double edge = ::basegfx::pruneScaleValue(
+ static_cast<double>( static_cast<sal_Int32>(sqrtArea2) ) /
+ m_sqrtElements );
+
+ ::basegfx::B2DPolygon poly;
+ if (! ::basegfx::fTools::equalZero( edge )) {
+ poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) );
+ poly.append( ::basegfx::B2DPoint( 0.0, edge ) );
+ poly.append( ::basegfx::B2DPoint( edge, 0.0 ) );
+ poly.setClosed(true);
+ res.append(poly);
+ }
+ const double a = (M_SQRT1_2 / m_sqrtElements);
+ const double d = (sqrtArea2 - static_cast<sal_Int32>(sqrtArea2));
+ const double len = (t * M_SQRT2 * d);
+ const double height = ::basegfx::pruneScaleValue( M_SQRT1_2 / m_sqrtElements );
+ poly.clear();
+ poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) );
+ poly.append( ::basegfx::B2DPoint( 0.0, height ) );
+ poly.append( ::basegfx::B2DPoint( len + a, height ) );
+ poly.append( ::basegfx::B2DPoint( len + a, 0.0 ) );
+ poly.setClosed(true);
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if ((static_cast<sal_Int32>(sqrtArea2) & 1) == 1)
+ {
+ // odd line
+ aTransform = basegfx::tools::createRotateB2DHomMatrix(M_PI_2 + M_PI_4);
+ aTransform.translate(edge + m_elementEdge, 0.0);
+ }
+ else
+ {
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(-a, 0.0);
+ aTransform.rotate( -M_PI_4 );
+ aTransform.translate( 0.0, edge );
+ }
+
+ poly.transform( aTransform );
+ res.append(poly);
+ }
+ else // out
+ {
+ const double sqrtArea2 = sqrt( t * m_sqrtElements * m_sqrtElements );
+ const double edge = ::basegfx::pruneScaleValue(
+ static_cast<double>( static_cast<sal_Int32>(sqrtArea2) ) /
+ m_sqrtElements );
+
+ ::basegfx::B2DPolygon poly;
+ if (! ::basegfx::fTools::equalZero( edge )) {
+ poly.append( ::basegfx::B2DPoint( 0.0, 1.0 ) );
+ poly.append( ::basegfx::B2DPoint( edge, 1.0 ) );
+ poly.append( ::basegfx::B2DPoint( 1.0, edge ) );
+ poly.append( ::basegfx::B2DPoint( 1.0, 0.0 ) );
+ poly.setClosed(true);
+ res.append(poly);
+ }
+ const double a = (M_SQRT1_2 / m_sqrtElements);
+ const double d = (sqrtArea2 - static_cast<sal_Int32>(sqrtArea2));
+ const double len = ((1.0 - t) * M_SQRT2 * d);
+ const double height = ::basegfx::pruneScaleValue( M_SQRT1_2 / m_sqrtElements );
+ poly.clear();
+ poly.append( ::basegfx::B2DPoint( 0.0, 0.0 ) );
+ poly.append( ::basegfx::B2DPoint( 0.0, height ) );
+ poly.append( ::basegfx::B2DPoint( len + a, height ) );
+ poly.append( ::basegfx::B2DPoint( len + a, 0.0 ) );
+ poly.setClosed(true);
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if ((static_cast<sal_Int32>(sqrtArea2) & 1) == 1)
+ {
+ // odd line
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(0.0, -height);
+ aTransform.rotate( M_PI_2 + M_PI_4 );
+ aTransform.translate( 1.0, edge );
+ }
+ else
+ {
+ aTransform = basegfx::tools::createRotateB2DHomMatrix(-M_PI_4);
+ aTransform.translate( edge, 1.0 );
+ }
+ poly.transform( aTransform );
+ res.append(poly);
+ }
+
+ return res;
+}
+
+::basegfx::B2DPolyPolygon SnakeWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res;
+ if (m_diagonal)
+ {
+ if (t >= 0.5) {
+ res.append( calcHalfDiagonalSnake( 1.0, true ) );
+ res.append( calcHalfDiagonalSnake( 2.0 * (t - 0.5), false ) );
+ }
+ else
+ res.append( calcHalfDiagonalSnake( 2.0 * t, true ) );
+ }
+ else
+ res = calcSnake(t);
+
+ return m_flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+::basegfx::B2DPolyPolygon ParallelSnakesWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res;
+ if (m_diagonal)
+ {
+ OSL_ASSERT( m_opposite );
+ ::basegfx::B2DPolyPolygon half(
+ calcHalfDiagonalSnake( t, false /* out */ ) );
+ // flip on x axis and rotate 90 degrees:
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleB2DHomMatrix(1.0, -1.0));
+ aTransform.translate( -0.5, 0.5 );
+ aTransform.rotate( M_PI_2 );
+ aTransform.translate( 0.5, 0.5 );
+ half.transform( aTransform );
+ half.flip();
+ res.append( half );
+
+ // rotate 180 degrees:
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5);
+ aTransform.rotate( M_PI );
+ aTransform.translate( 0.5, 0.5 );
+ half.transform( aTransform );
+ res.append( half );
+ }
+ else
+ {
+ ::basegfx::B2DPolyPolygon half( calcSnake( t / 2.0 ) );
+ // rotate 90 degrees:
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5));
+ aTransform.rotate( M_PI_2 );
+ aTransform.translate( 0.5, 0.5 );
+ half.transform( aTransform );
+ res.append( flipOnYAxis(half) );
+ res.append( m_opposite ? flipOnXAxis(half) : half );
+ }
+
+ return m_flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/snakewipe.hxx b/slideshow/source/engine/transitions/snakewipe.hxx
new file mode 100644
index 000000000000..3b14944d7d68
--- /dev/null
+++ b/slideshow/source/engine/transitions/snakewipe.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_SNAKEWIPE_HXX
+#define INCLUDED_SLIDESHOW_SNAKEWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a snake wipe:
+class SnakeWipe : public ParametricPolyPolygon
+{
+public:
+ SnakeWipe( sal_Int32 nElements, bool diagonal, bool flipOnYAxis );
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+
+protected:
+ // topLeftHorizontal:
+ ::basegfx::B2DPolyPolygon calcSnake( double t ) const;
+ // topLeftDiagonal:
+ ::basegfx::B2DPolyPolygon calcHalfDiagonalSnake( double t, bool in ) const;
+
+ const sal_Int32 m_sqrtElements;
+ const double m_elementEdge;
+ const bool m_diagonal;
+ const bool m_flipOnYAxis;
+};
+
+/// Generates a parallel snakes wipe:
+class ParallelSnakesWipe : public SnakeWipe
+{
+public:
+ ParallelSnakesWipe( sal_Int32 nElements,
+ bool diagonal, bool flipOnYAxis, bool opposite )
+ : SnakeWipe( nElements, diagonal, flipOnYAxis ),
+ m_opposite( opposite )
+ {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ const bool m_opposite;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_SNAKEWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/spiralwipe.cxx b/slideshow/source/engine/transitions/spiralwipe.cxx
new file mode 100644
index 000000000000..2ddee7226e91
--- /dev/null
+++ b/slideshow/source/engine/transitions/spiralwipe.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include "spiralwipe.hxx"
+#include "transitiontools.hxx"
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+
+namespace slideshow {
+namespace internal {
+
+SpiralWipe::SpiralWipe( sal_Int32 nElements, bool flipOnYAxis )
+ : m_elements(nElements),
+ m_sqrtElements( static_cast<sal_Int32>(
+ sqrt( static_cast<double>(nElements) ) ) ),
+ m_flipOnYAxis(flipOnYAxis)
+{
+}
+
+::basegfx::B2DPolyPolygon SpiralWipe::calcNegSpiral( double t ) const
+{
+ const double area = (t * m_elements);
+ const double e = (sqrt(area) / 2.0);
+ const sal_Int32 edge = (static_cast<sal_Int32>(e) * 2);
+
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5));
+ const double edge_ = ::basegfx::pruneScaleValue(
+ static_cast<double>(edge) / m_sqrtElements );
+ aTransform.scale( edge_, edge_ );
+ aTransform.translate( 0.5, 0.5 );
+ ::basegfx::B2DPolygon poly( createUnitRect() );
+ poly.transform( aTransform );
+ ::basegfx::B2DPolyPolygon res(poly);
+
+ if (! ::basegfx::fTools::equalZero( 1.0 - t )) {
+ const sal_Int32 edge1 = (edge + 1);
+ sal_Int32 len = static_cast<sal_Int32>( (e - (edge /2)) * edge1 * 4 );
+ double w = M_PI_2;
+ while (len > 0) {
+ const sal_Int32 alen = (len > edge1 ? edge1 : len);
+ len -= alen;
+ poly = createUnitRect();
+ aTransform = basegfx::tools::createScaleB2DHomMatrix(
+ ::basegfx::pruneScaleValue( static_cast<double>(alen) / m_sqrtElements ),
+ ::basegfx::pruneScaleValue( 1.0 / m_sqrtElements ) );
+ aTransform.translate(
+ - ::basegfx::pruneScaleValue(
+ static_cast<double>(edge / 2) / m_sqrtElements ),
+ ::basegfx::pruneScaleValue(
+ static_cast<double>(edge / 2) / m_sqrtElements ) );
+ aTransform.rotate( w );
+ w -= M_PI_2;
+ aTransform.translate( 0.5, 0.5 );
+ poly.transform( aTransform );
+ res.append(poly);
+ }
+ }
+
+ return res;
+}
+
+::basegfx::B2DPolyPolygon SpiralWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res( createUnitRect() );
+ ::basegfx::B2DPolyPolygon innerSpiral( calcNegSpiral( 1.0 - t ) );
+ innerSpiral.flip();
+ res.append(innerSpiral);
+ return m_flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+::basegfx::B2DPolyPolygon BoxSnakesWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res( createUnitRect() );
+ ::basegfx::B2DPolyPolygon innerSpiral( calcNegSpiral( 1.0 - t ) );
+ innerSpiral.flip();
+
+ if (m_fourBox) {
+ ::basegfx::B2DHomMatrix aTransform;
+ aTransform.scale( 0.5, 0.5 );
+ innerSpiral.transform( aTransform );
+ res.append(innerSpiral);
+ res.append( flipOnXAxis(innerSpiral) );
+ innerSpiral = flipOnYAxis(innerSpiral);
+ res.append(innerSpiral);
+ res.append( flipOnXAxis(innerSpiral) );
+ }
+ else {
+ ::basegfx::B2DHomMatrix aTransform;
+ aTransform.scale( 1.0, 0.5 );
+ innerSpiral.transform( aTransform );
+ res.append(innerSpiral);
+ res.append( flipOnXAxis(innerSpiral) );
+ }
+
+ return m_flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/spiralwipe.hxx b/slideshow/source/engine/transitions/spiralwipe.hxx
new file mode 100644
index 000000000000..4e11e2df9ed1
--- /dev/null
+++ b/slideshow/source/engine/transitions/spiralwipe.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_SPIRALWIPE_HXX
+#define INCLUDED_SLIDESHOW_SPIRALWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a topLeftClockWise or
+/// bottomLeftCounterClockWise (flipOnYAxis=true) spiral wipe:
+class SpiralWipe : public ParametricPolyPolygon
+{
+public:
+ SpiralWipe( sal_Int32 nElements, bool flipOnYAxis = false );
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+protected:
+ ::basegfx::B2DPolyPolygon calcNegSpiral( double t ) const;
+
+ const sal_Int32 m_elements;
+ const sal_Int32 m_sqrtElements;
+ const bool m_flipOnYAxis;
+};
+
+/// Generates a twoBoxLeft or fourBoxHorizontal wipe:
+class BoxSnakesWipe : public SpiralWipe
+{
+public:
+ BoxSnakesWipe( sal_Int32 nElements, bool fourBox = false )
+ : SpiralWipe(nElements), m_fourBox(fourBox) {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ const bool m_fourBox;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_SPIRALWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/sweepwipe.cxx b/slideshow/source/engine/transitions/sweepwipe.cxx
new file mode 100644
index 000000000000..ae743ec23944
--- /dev/null
+++ b/slideshow/source/engine/transitions/sweepwipe.cxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "clockwipe.hxx"
+#include "sweepwipe.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon SweepWipe::operator () ( double t )
+{
+ t /= 2.0;
+ if (! m_center)
+ t /= 2.0;
+ if (!m_single && !m_oppositeVertical)
+ t /= 2.0;
+
+ ::basegfx::B2DPolygon poly( ClockWipe::calcCenteredClock( 0.25 + t ) );
+ ::basegfx::B2DHomMatrix aTransform;
+
+ if (m_center)
+ {
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.0);
+ poly.transform( aTransform );
+ }
+ ::basegfx::B2DPolyPolygon res(poly);
+
+ if (! m_single)
+ {
+ if (m_oppositeVertical)
+ {
+ aTransform = basegfx::tools::createScaleB2DHomMatrix(1.0, -1.0);
+ aTransform.translate( 0.0, 1.0 );
+ poly.transform( aTransform );
+ poly.flip();
+ }
+ else
+ {
+ aTransform = basegfx::tools::createTranslateB2DHomMatrix(-0.5, -0.5);
+ aTransform.rotate( M_PI );
+ aTransform.translate( 0.5, 0.5 );
+ poly.transform( aTransform );
+ }
+ res.append(poly);
+ }
+
+ return m_flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/sweepwipe.hxx b/slideshow/source/engine/transitions/sweepwipe.hxx
new file mode 100644
index 000000000000..c1e9fc3327b1
--- /dev/null
+++ b/slideshow/source/engine/transitions/sweepwipe.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_SWEEPWIPE_HXX
+#define INCLUDED_SLIDESHOW_SWEEPWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+class SweepWipe : public ParametricPolyPolygon
+{
+public:
+ SweepWipe( bool center, bool single,
+ bool oppositeVertical, bool flipOnYAxis )
+ : m_center(center), m_single(single),
+ m_oppositeVertical(oppositeVertical), m_flipOnYAxis(flipOnYAxis)
+ {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ const bool m_center, m_single, m_oppositeVertical, m_flipOnYAxis;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_SWEEPWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/transitionfactorytab.cxx b/slideshow/source/engine/transitions/transitionfactorytab.cxx
new file mode 100644
index 000000000000..052c0ab045ee
--- /dev/null
+++ b/slideshow/source/engine/transitions/transitionfactorytab.cxx
@@ -0,0 +1,2149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <boost/current_function.hpp>
+#include <basegfx/numeric/ftools.hxx>
+#include <com/sun/star/animations/TransitionType.hpp>
+#include <com/sun/star/animations/TransitionSubType.hpp>
+
+#include "transitionfactory.hxx"
+#include "tools.hxx"
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+static const TransitionInfo lcl_transitionInfo[] =
+{
+ {
+ 0,
+ 0,
+ TransitionInfo::TRANSITION_INVALID,
+ 0.0,
+ 0.0,
+ 0.0,
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ false,
+ false
+ },
+ {
+ // mapped to BarWipePolyPolygon:
+ animations::TransitionType::BARWIPE,
+ animations::TransitionSubType::LEFTTORIGHT, // (1)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ false, // 'out' by subtraction
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarWipePolyPolygon:
+ animations::TransitionType::BARWIPE,
+ animations::TransitionSubType::TOPTOBOTTOM, // (2)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ false, // 'out' by subtraction
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to BarWipePolyPolygon(nBars=5):
+ animations::TransitionType::BLINDSWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarWipePolyPolygon(nBars=5):
+ animations::TransitionType::BLINDSWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::TOPLEFT, // (3)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // possible via bottomRight
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::TOPRIGHT, // (4)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // possible via bottomLeft
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::BOTTOMRIGHT, // (5)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // possible via topLeft
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::BOTTOMLEFT, // (6)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // possible via topRight
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::TOPCENTER, // (23)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::RIGHTCENTER, // (24)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::BOTTOMCENTER, // (25)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxWipe:
+ animations::TransitionType::BOXWIPE,
+ animations::TransitionSubType::LEFTCENTER, // (26)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FourBoxWipe:
+ animations::TransitionType::FOURBOXWIPE,
+ animations::TransitionSubType::CORNERSIN, // (7)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FourBoxWipe:
+ animations::TransitionType::FOURBOXWIPE,
+ animations::TransitionSubType::CORNERSOUT, // (8)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to BarnDoorWipe:
+ animations::TransitionType::BARNDOORWIPE,
+ animations::TransitionSubType::VERTICAL, // (21)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarnDoorWipe:
+ animations::TransitionType::BARNDOORWIPE,
+ animations::TransitionSubType::HORIZONTAL, // (22)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarnDoorWipe:
+ animations::TransitionType::BARNDOORWIPE,
+ animations::TransitionSubType::DIAGONALBOTTOMLEFT, // (45)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 45.0, // rotation
+ M_SQRT2, // scaling
+ M_SQRT2, // scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarnDoorWipe:
+ animations::TransitionType::BARNDOORWIPE,
+ animations::TransitionSubType::DIAGONALTOPLEFT, // (46)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -45.0, // rotation
+ M_SQRT2, // scaling
+ M_SQRT2, // scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to BarWipePolyPolygon:
+ animations::TransitionType::DIAGONALWIPE,
+ animations::TransitionSubType::TOPLEFT, // (41)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 45.0, // rotation
+ M_SQRT2, // scaling
+ M_SQRT2, // scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarWipePolyPolygon:
+ animations::TransitionType::DIAGONALWIPE,
+ animations::TransitionSubType::TOPRIGHT, // (42)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 135.0, // rotation
+ M_SQRT2, // scaling
+ M_SQRT2, // scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+
+ {
+ animations::TransitionType::BOWTIEWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::BOWTIEWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to BarnDoorWipe (doubled=true):
+ animations::TransitionType::MISCDIAGONALWIPE,
+ animations::TransitionSubType::DOUBLEBARNDOOR, // (47)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 45.0, // rotation
+ M_SQRT2, // scaling
+ M_SQRT2, // scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to DoubleDiamondWipe:
+ animations::TransitionType::MISCDIAGONALWIPE,
+ animations::TransitionSubType::DOUBLEDIAMOND, // (48)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to VeeWipe:
+ animations::TransitionType::VEEWIPE,
+ animations::TransitionSubType::DOWN, // (61)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to VeeWipe:
+ animations::TransitionType::VEEWIPE,
+ animations::TransitionSubType::LEFT, // (62)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::VEEWIPE,
+ animations::TransitionSubType::UP, // (63)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::VEEWIPE,
+ animations::TransitionSubType::RIGHT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+
+ {
+ animations::TransitionType::BARNVEEWIPE,
+ animations::TransitionSubType::TOP,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::BARNVEEWIPE,
+ animations::TransitionSubType::LEFT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::BARNVEEWIPE,
+ animations::TransitionSubType::UP,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::BARNVEEWIPE,
+ animations::TransitionSubType::RIGHT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to ZigZagWipe:
+ animations::TransitionType::ZIGZAGWIPE,
+ animations::TransitionSubType::LEFTTORIGHT, // (71)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ZigZagWipe:
+ animations::TransitionType::ZIGZAGWIPE,
+ animations::TransitionSubType::TOPTOBOTTOM, // (72)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarnZigZagWipe:
+ animations::TransitionType::BARNZIGZAGWIPE,
+ animations::TransitionSubType::VERTICAL, // (73)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BarnZigZagWipe:
+ animations::TransitionType::BARNZIGZAGWIPE,
+ animations::TransitionSubType::HORIZONTAL, // (74)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to IrisWipe:
+ animations::TransitionType::IRISWIPE,
+ animations::TransitionSubType::RECTANGLE, // (101)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to IrisWipe:
+ animations::TransitionType::IRISWIPE,
+ animations::TransitionSubType::DIAMOND, // (102)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 45.0, // rotation
+ M_SQRT2, // scaling
+ M_SQRT2, // scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+
+ {
+ // mapped to FigureWipe(triangle):
+ animations::TransitionType::TRIANGLEWIPE,
+ animations::TransitionSubType::UP, // (103)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(triangle):
+ animations::TransitionType::TRIANGLEWIPE,
+ animations::TransitionSubType::RIGHT, // (104)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(triangle):
+ animations::TransitionType::TRIANGLEWIPE,
+ animations::TransitionSubType::DOWN, // (105)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(triangle):
+ animations::TransitionType::TRIANGLEWIPE,
+ animations::TransitionSubType::LEFT, // (106)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 270.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FigureWipe(arrowHead):
+ animations::TransitionType::ARROWHEADWIPE,
+ animations::TransitionSubType::UP, // (107)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(arrowHead):
+ animations::TransitionType::ARROWHEADWIPE,
+ animations::TransitionSubType::RIGHT, // (108)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(arrowHead):
+ animations::TransitionType::ARROWHEADWIPE,
+ animations::TransitionSubType::DOWN, // (109)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(arrowHead):
+ animations::TransitionType::ARROWHEADWIPE,
+ animations::TransitionSubType::LEFT, // (110)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 270.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FigureWipe(pentagon):
+ animations::TransitionType::PENTAGONWIPE,
+ animations::TransitionSubType::UP, // (111)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(pentagon):
+ animations::TransitionType::PENTAGONWIPE,
+ animations::TransitionSubType::DOWN, // (112)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FigureWipe(hexagon):
+ animations::TransitionType::HEXAGONWIPE,
+ animations::TransitionSubType::HORIZONTAL, // (113)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(hexagon):
+ animations::TransitionType::HEXAGONWIPE,
+ animations::TransitionSubType::VERTICAL, // (114)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to EllipseWipe:
+ animations::TransitionType::ELLIPSEWIPE,
+ animations::TransitionSubType::CIRCLE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size
+ },
+ {
+ // mapped to EllipseWipe:
+ animations::TransitionType::ELLIPSEWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to EllipseWipe:
+ animations::TransitionType::ELLIPSEWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+
+ {
+ animations::TransitionType::EYEWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::EYEWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::ROUNDRECTWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::ROUNDRECTWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FigureWipe(star, points=4):
+ animations::TransitionType::STARWIPE,
+ animations::TransitionSubType::FOURPOINT, // (127)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(star, points=5):
+ animations::TransitionType::STARWIPE,
+ animations::TransitionSubType::FIVEPOINT, // (128)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FigureWipe(star, points=6):
+ animations::TransitionType::STARWIPE,
+ animations::TransitionSubType::SIXPOINT, // (129)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ animations::TransitionType::MISCSHAPEWIPE,
+ animations::TransitionSubType::HEART,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::MISCSHAPEWIPE,
+ animations::TransitionSubType::KEYHOLE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to ClockWipe:
+ animations::TransitionType::CLOCKWIPE,
+ animations::TransitionSubType::CLOCKWISETWELVE, // (201)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ClockWipe:
+ animations::TransitionType::CLOCKWIPE,
+ animations::TransitionSubType::CLOCKWISETHREE, // (202)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ClockWipe:
+ animations::TransitionType::CLOCKWIPE,
+ animations::TransitionSubType::CLOCKWISESIX, // (203)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ClockWipe:
+ animations::TransitionType::CLOCKWIPE,
+ animations::TransitionSubType::CLOCKWISENINE, // (204)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 270.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to PinWheelWipe:
+ animations::TransitionType::PINWHEELWIPE,
+ animations::TransitionSubType::ONEBLADE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size, like ppt
+ },
+ {
+ // mapped to PinWheelWipe:
+ animations::TransitionType::PINWHEELWIPE,
+ animations::TransitionSubType::TWOBLADEVERTICAL, // (205)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size, like ppt
+ },
+ {
+ // mapped to PinWheelWipe:
+ animations::TransitionType::PINWHEELWIPE,
+ animations::TransitionSubType::TWOBLADEHORIZONTAL, // (206)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size, like ppt
+ },
+ {
+ // mapped to PinWheelWipe:
+ animations::TransitionType::PINWHEELWIPE,
+ animations::TransitionSubType::THREEBLADE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size, like ppt
+ },
+ {
+ // mapped to PinWheelWipe:
+ animations::TransitionType::PINWHEELWIPE,
+ animations::TransitionSubType::FOURBLADE, // (207)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size, like ppt
+ },
+ {
+ // mapped to PinWheelWipe:
+ animations::TransitionType::PINWHEELWIPE,
+ animations::TransitionSubType::EIGHTBLADE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size, like ppt
+ },
+
+ {
+ // mapped to SweepWipe (center=true, single=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::CLOCKWISETOP, // (221)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=true, single=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::CLOCKWISERIGHT, // (222)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=true, single=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::CLOCKWISEBOTTOM, // (223)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=true, single=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::CLOCKWISELEFT, // (224)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 270.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=false, single=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::CLOCKWISETOPLEFT, // (241)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=false, single=true, flipOnYAxis=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::COUNTERCLOCKWISEBOTTOMLEFT, // (242)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=false, single=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::CLOCKWISEBOTTOMRIGHT, // (243)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=false, single=true, flipOnYAxis=true):
+ animations::TransitionType::SINGLESWEEPWIPE,
+ animations::TransitionSubType::COUNTERCLOCKWISETOPRIGHT, // (244)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FanWipe(center=true):
+ animations::TransitionType::FANWIPE,
+ animations::TransitionSubType::CENTERTOP, // (211)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe(center=true):
+ animations::TransitionType::FANWIPE,
+ animations::TransitionSubType::CENTERRIGHT, // (212)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe:
+ animations::TransitionType::FANWIPE,
+ animations::TransitionSubType::TOP, // (231)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe:
+ animations::TransitionType::FANWIPE,
+ animations::TransitionSubType::RIGHT, // (232)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe:
+ animations::TransitionType::FANWIPE,
+ animations::TransitionSubType::BOTTOM, // (233)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe:
+ animations::TransitionType::FANWIPE,
+ animations::TransitionSubType::LEFT, // (234)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to FanWipe(center=true, single=false, fanIn=false):
+ animations::TransitionType::DOUBLEFANWIPE,
+ animations::TransitionSubType::FANOUTVERTICAL, // (213)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe(center=true, single=false, fanIn=false):
+ animations::TransitionType::DOUBLEFANWIPE,
+ animations::TransitionSubType::FANOUTHORIZONTAL, // (214)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe(center=true, single=false, fanIn=true):
+ animations::TransitionType::DOUBLEFANWIPE,
+ animations::TransitionSubType::FANINVERTICAL, // (235)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to FanWipe(center=true, single=false, fanIn=true):
+ animations::TransitionType::DOUBLEFANWIPE,
+ animations::TransitionSubType::FANINHORIZONTAL, // (236)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to SweepWipe (center=true, single=false):
+ animations::TransitionType::DOUBLESWEEPWIPE,
+ animations::TransitionSubType::PARALLELVERTICAL, // (225)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=true, single=false):
+ animations::TransitionType::DOUBLESWEEPWIPE,
+ animations::TransitionSubType::PARALLELDIAGONAL, // (226)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=true, single=false,
+ // oppositeVertical=true):
+ animations::TransitionType::DOUBLESWEEPWIPE,
+ animations::TransitionSubType::OPPOSITEVERTICAL, // (227)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=true, single=false,
+ // oppositeVertical=true):
+ animations::TransitionType::DOUBLESWEEPWIPE,
+ animations::TransitionSubType::OPPOSITEHORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=false, single=false):
+ animations::TransitionType::DOUBLESWEEPWIPE,
+ animations::TransitionSubType::PARALLELDIAGONALTOPLEFT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SweepWipe (center=false, single=false):
+ animations::TransitionType::DOUBLESWEEPWIPE,
+ animations::TransitionSubType::PARALLELDIAGONALBOTTOMLEFT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ animations::TransitionType::SALOONDOORWIPE,
+ animations::TransitionSubType::TOP, // (251)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SALOONDOORWIPE,
+ animations::TransitionSubType::LEFT, // (252)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SALOONDOORWIPE,
+ animations::TransitionSubType::BOTTOM, // (253)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SALOONDOORWIPE,
+ animations::TransitionSubType::RIGHT, // (254)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::WINDSHIELDWIPE,
+ animations::TransitionSubType::RIGHT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::WINDSHIELDWIPE,
+ animations::TransitionSubType::UP,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::WINDSHIELDWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::WINDSHIELDWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to SnakeWipe:
+ animations::TransitionType::SNAKEWIPE,
+ animations::TransitionSubType::TOPLEFTHORIZONTAL, // (301)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SnakeWipe(flipOnYAxis=true):
+ animations::TransitionType::SNAKEWIPE,
+ animations::TransitionSubType::TOPLEFTVERTICAL, // (302)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SnakeWipe(diagonal=true):
+ animations::TransitionType::SNAKEWIPE,
+ animations::TransitionSubType::TOPLEFTDIAGONAL, // (303)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SnakeWipe(diagonal=true, flipOnYAxis=true):
+ animations::TransitionType::SNAKEWIPE,
+ animations::TransitionSubType::TOPRIGHTDIAGONAL, // (304)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SnakeWipe(diagonal=true):
+ animations::TransitionType::SNAKEWIPE,
+ animations::TransitionSubType::BOTTOMRIGHTDIAGONAL, // (305)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SnakeWipe(diagonal=true, flipOnYAxis=true):
+ animations::TransitionType::SNAKEWIPE,
+ animations::TransitionSubType::BOTTOMLEFTDIAGONAL, // (306)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to SpiralWipe:
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::TOPLEFTCLOCKWISE, // (310)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe:
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::TOPRIGHTCLOCKWISE, // (311)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe:
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::BOTTOMRIGHTCLOCKWISE, // (312)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe:
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::BOTTOMLEFTCLOCKWISE, // (313)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 270.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe(flipOnYAxis=true):
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::TOPLEFTCOUNTERCLOCKWISE, // (314)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe(flipOnYAxis=true):
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::TOPRIGHTCOUNTERCLOCKWISE, // (315)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe(flipOnYAxis=true):
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::BOTTOMRIGHTCOUNTERCLOCKWISE, // (316)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 270.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to SpiralWipe(flipOnYAxis=true):
+ animations::TransitionType::SPIRALWIPE,
+ animations::TransitionSubType::BOTTOMLEFTCOUNTERCLOCKWISE, // (317)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to ParallelSnakesWipe:
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::VERTICALTOPSAME,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe:
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::VERTICALBOTTOMSAME,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe (opposite=true):
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::VERTICALTOPLEFTOPPOSITE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe (flipOnYAxis=true, opposite=true):
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::VERTICALBOTTOMLEFTOPPOSITE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe:
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::HORIZONTALLEFTSAME,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe:
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::HORIZONTALRIGHTSAME,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe (flipOnYAxis=true, opposite=true):
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::HORIZONTALTOPLEFTOPPOSITE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe (opposite=true):
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::HORIZONTALTOPRIGHTOPPOSITE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe (diagonal=true, opposite=true):
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::DIAGONALBOTTOMLEFTOPPOSITE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to ParallelSnakesWipe (diagonal=true, opposite=true,
+ // flipOnYAxis=true):
+ animations::TransitionType::PARALLELSNAKESWIPE,
+ animations::TransitionSubType::DIAGONALTOPLEFTOPPOSITE,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to BoxSnakesWipe:
+ animations::TransitionType::BOXSNAKESWIPE,
+ animations::TransitionSubType::TWOBOXTOP, // (340)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxSnakesWipe:
+ animations::TransitionType::BOXSNAKESWIPE,
+ animations::TransitionSubType::TWOBOXBOTTOM, // (341)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxSnakesWipe:
+ animations::TransitionType::BOXSNAKESWIPE,
+ animations::TransitionSubType::TWOBOXLEFT, // (342)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxSnakesWipe:
+ animations::TransitionType::BOXSNAKESWIPE,
+ animations::TransitionSubType::TWOBOXRIGHT, // (343)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 180.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxSnakesWipe(fourBox=true):
+ animations::TransitionType::BOXSNAKESWIPE,
+ animations::TransitionSubType::FOURBOXVERTICAL, // (344)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to BoxSnakesWipe(fourBox=true):
+ animations::TransitionType::BOXSNAKESWIPE,
+ animations::TransitionSubType::FOURBOXHORIZONTAL, // (345)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to WaterfallWipe:
+ animations::TransitionType::WATERFALLWIPE,
+ animations::TransitionSubType::VERTICALLEFT, // (350)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to WaterfallWipe (flipOnYAxis=true):
+ animations::TransitionType::WATERFALLWIPE,
+ animations::TransitionSubType::VERTICALRIGHT, // (351)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to WaterfallWipe (flipOnYAxis=true):
+ animations::TransitionType::WATERFALLWIPE,
+ animations::TransitionSubType::HORIZONTALLEFT, // (352)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ -90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to WaterfallWipe, flipOnYAxis=false:
+ animations::TransitionType::WATERFALLWIPE,
+ animations::TransitionSubType::HORIZONTALRIGHT, // (353)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_ROTATE_180,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMLEFT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMTOP,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMRIGHT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMBOTTOM,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMBOTTOMRIGHT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMBOTTOMLEFT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMTOPRIGHT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::FROMTOPLEFT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::COMBHORIZONTAL,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::PUSHWIPE,
+ animations::TransitionSubType::COMBVERTICAL,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMLEFT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMTOP,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMRIGHT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMBOTTOM,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMBOTTOMRIGHT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMTOPRIGHT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMTOPLEFT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::SLIDEWIPE,
+ animations::TransitionSubType::FROMBOTTOMLEFT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE, // special code for this transition
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::FADE,
+ animations::TransitionSubType::CROSSFADE,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::FADE,
+ animations::TransitionSubType::FADETOCOLOR,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::FADE,
+ animations::TransitionSubType::FADEFROMCOLOR,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ animations::TransitionType::FADE,
+ animations::TransitionSubType::FADEOVERCOLOR,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ // this is the cut through black fade (does not fade, but does a
+ // hard cut)
+ {
+ animations::TransitionType::BARWIPE,
+ animations::TransitionSubType::FADEOVERCOLOR,
+ TransitionInfo::TRANSITION_SPECIAL,
+ // TODO(F2): Setup parameters
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to RandomWipe:
+ animations::TransitionType::RANDOMBARWIPE,
+ animations::TransitionSubType::VERTICAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to RandomWipe:
+ animations::TransitionType::RANDOMBARWIPE,
+ animations::TransitionSubType::HORIZONTAL,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to CheckerBoard:
+ animations::TransitionType::CHECKERBOARDWIPE,
+ animations::TransitionSubType::DOWN,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 90.0, // rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_Y,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+ {
+ // mapped to CheckerBoard:
+ animations::TransitionType::CHECKERBOARDWIPE,
+ animations::TransitionSubType::ACROSS, // (default)
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_FLIP_X,
+ true, // 'out' by parameter sweep inversion
+ false // scale isotrophically to target size
+ },
+
+ {
+ // mapped to RandomWipe:
+ animations::TransitionType::DISSOLVE,
+ animations::TransitionSubType::DEFAULT,
+ TransitionInfo::TRANSITION_CLIP_POLYPOLYGON,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size
+ },
+
+ /////////////////////////////////////////////////////////
+ // NOTE: This entry MUST be the last, to keep
+ // createSlideTransition() from infinite recursion. Because
+ // getRandomTransitionInfo() below will exclude the last entry of
+ // the table from the random number generation.
+ /////////////////////////////////////////////////////////
+ {
+ // specially handled
+ animations::TransitionType::RANDOM,
+ animations::TransitionSubType::DEFAULT,
+ TransitionInfo::TRANSITION_SPECIAL,
+ 0.0, // no rotation
+ 1.0, // no scaling
+ 1.0, // no scaling
+ TransitionInfo::REVERSEMETHOD_IGNORE,
+ true, // 'out' by parameter sweep inversion
+ true // scale isotrophically to target size
+ }
+ /////////////////////////////////////////////////////////
+ // NOTE: DON'T add after this entry! See comment above!
+ /////////////////////////////////////////////////////////
+};
+
+} // anon namespace
+
+const TransitionInfo* TransitionFactory::getTransitionInfo(
+ sal_Int16 nTransitionType, sal_Int16 nTransitionSubType )
+{
+ static const ::std::size_t lcl_tableSize(
+ sizeof(lcl_transitionInfo)/sizeof(TransitionInfo) );
+ static const TransitionInfo* pTableEnd = lcl_transitionInfo+lcl_tableSize;
+
+ const TransitionInfo* pRes = ::std::find_if(
+ lcl_transitionInfo, pTableEnd,
+ TransitionInfo::Comparator( nTransitionType,
+ nTransitionSubType ) );
+ if (pRes != pTableEnd)
+ return pRes;
+ else
+ return NULL;
+}
+
+const TransitionInfo* TransitionFactory::getRandomTransitionInfo()
+{
+ return lcl_transitionInfo + getRandomOrdinal(
+ sizeof(lcl_transitionInfo) / sizeof(TransitionInfo)
+ - 1 /* exclude random transition at end of table */ );
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/transitiontools.cxx b/slideshow/source/engine/transitions/transitiontools.cxx
new file mode 100644
index 000000000000..c2cc7c50bd27
--- /dev/null
+++ b/slideshow/source/engine/transitions/transitiontools.cxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include "transitiontools.hxx"
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+
+namespace slideshow {
+namespace internal {
+
+// TODO(Q2): Move this to basegfx
+::basegfx::B2DPolygon createUnitRect()
+{
+ return ::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle(0.0,0.0,
+ 1.0,1.0 ) );
+}
+
+::basegfx::B2DPolyPolygon flipOnYAxis(
+ ::basegfx::B2DPolyPolygon const & polypoly )
+{
+ ::basegfx::B2DPolyPolygon res(polypoly);
+ res.transform(basegfx::tools::createScaleTranslateB2DHomMatrix(-1.0, 1.0, 1.0, 0.0));
+ res.flip();
+ return res;
+}
+
+::basegfx::B2DPolyPolygon flipOnXAxis(
+ ::basegfx::B2DPolyPolygon const & polypoly )
+{
+ ::basegfx::B2DPolyPolygon res(polypoly);
+ res.transform(basegfx::tools::createScaleTranslateB2DHomMatrix(1.0, -1.0, 0.0, 1.0));
+ res.flip();
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/transitiontools.hxx b/slideshow/source/engine/transitions/transitiontools.hxx
new file mode 100644
index 000000000000..c8c95ad7e48d
--- /dev/null
+++ b/slideshow/source/engine/transitions/transitiontools.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_TRANSITIONTOOLS_HXX
+#define INCLUDED_SLIDESHOW_TRANSITIONTOOLS_HXX
+
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <algorithm>
+
+
+namespace slideshow {
+namespace internal {
+
+/// Create a unit rect.
+::basegfx::B2DPolygon createUnitRect();
+
+/// Flips on X-axis:
+::basegfx::B2DPolyPolygon flipOnXAxis(
+ ::basegfx::B2DPolyPolygon const & polypoly );
+
+/// Flips on Y-axis:
+::basegfx::B2DPolyPolygon flipOnYAxis(
+ ::basegfx::B2DPolyPolygon const & polypoly );
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_TRANSITIONTOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/veewipe.cxx b/slideshow/source/engine/transitions/veewipe.cxx
new file mode 100644
index 000000000000..47bc901019c4
--- /dev/null
+++ b/slideshow/source/engine/transitions/veewipe.cxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include "veewipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+::basegfx::B2DPolyPolygon VeeWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolygon poly;
+ poly.append( ::basegfx::B2DPoint( 0.0, -1.0 ) );
+ const double d = ::basegfx::pruneScaleValue( 2.0 * t );
+ poly.append( ::basegfx::B2DPoint( 0.0, d - 1.0 ) );
+ poly.append( ::basegfx::B2DPoint( 0.5, d ) );
+ poly.append( ::basegfx::B2DPoint( 1.0, d - 1.0 ) );
+ poly.append( ::basegfx::B2DPoint( 1.0, -1.0 ) );
+ poly.setClosed(true);
+ return ::basegfx::B2DPolyPolygon( poly );
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/veewipe.hxx b/slideshow/source/engine/transitions/veewipe.hxx
new file mode 100644
index 000000000000..b25816f6b1dc
--- /dev/null
+++ b/slideshow/source/engine/transitions/veewipe.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_VEEWIPE_HXX
+#define INCLUDED_SLIDESHOW_VEEWIPE_HXX
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include "parametricpolypolygon.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a vee wipe
+class VeeWipe : public ParametricPolyPolygon
+{
+public:
+ VeeWipe() {}
+ virtual ::basegfx::B2DPolyPolygon operator()( double x );
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_VEEWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/waterfallwipe.cxx b/slideshow/source/engine/transitions/waterfallwipe.cxx
new file mode 100644
index 000000000000..7ea4539c7227
--- /dev/null
+++ b/slideshow/source/engine/transitions/waterfallwipe.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "waterfallwipe.hxx"
+#include "transitiontools.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+WaterfallWipe::WaterfallWipe( sal_Int32 nElements, bool flipOnYAxis )
+ : m_flipOnYAxis( flipOnYAxis )
+{
+ const sal_Int32 sqrtElements = static_cast<sal_Int32>(
+ sqrt( static_cast<double>(nElements) ) );
+ const double elementEdge = (1.0 / sqrtElements);
+ m_waterfall.append( ::basegfx::B2DPoint( 0.0, -1.0 ) );
+ for ( sal_Int32 pos = sqrtElements; pos--; )
+ {
+ const sal_Int32 xPos = (sqrtElements - pos - 1);
+ const double yPos = ::basegfx::pruneScaleValue( ((pos + 1) * elementEdge) - 1.0 );
+ m_waterfall.append( ::basegfx::B2DPoint(
+ ::basegfx::pruneScaleValue( xPos * elementEdge ),
+ yPos ) );
+ m_waterfall.append( ::basegfx::B2DPoint(
+ ::basegfx::pruneScaleValue( (xPos + 1) * elementEdge ),
+ yPos ) );
+ }
+ m_waterfall.append( ::basegfx::B2DPoint( 1.0, -1.0 ) );
+ m_waterfall.setClosed(true);
+}
+
+::basegfx::B2DPolyPolygon WaterfallWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolygon poly( m_waterfall );
+ poly.transform(basegfx::tools::createTranslateB2DHomMatrix(0.0, ::basegfx::pruneScaleValue(2.0 * t)));
+ poly.setB2DPoint( 0, ::basegfx::B2DPoint( 0.0, -1.0 ) );
+ poly.setB2DPoint( poly.count()-1, ::basegfx::B2DPoint( 1.0, -1.0 ) );
+
+ return m_flipOnYAxis ? flipOnYAxis( ::basegfx::B2DPolyPolygon(poly) )
+ : ::basegfx::B2DPolyPolygon(poly);
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/waterfallwipe.hxx b/slideshow/source/engine/transitions/waterfallwipe.hxx
new file mode 100644
index 000000000000..58cf278e2916
--- /dev/null
+++ b/slideshow/source/engine/transitions/waterfallwipe.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_WATERFALLWIPE_HXX
+#define INCLUDED_SLIDESHOW_WATERFALLWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generate a vertical left waterfall wipe
+class WaterfallWipe : public ParametricPolyPolygon
+{
+public:
+ WaterfallWipe( sal_Int32 nElements, bool flipOnYAxis = false );
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+private:
+ bool m_flipOnYAxis;
+ ::basegfx::B2DPolygon m_waterfall;
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_WATERFALLWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/zigzagwipe.cxx b/slideshow/source/engine/transitions/zigzagwipe.cxx
new file mode 100644
index 000000000000..a0c57db35223
--- /dev/null
+++ b/slideshow/source/engine/transitions/zigzagwipe.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include "transitiontools.hxx"
+#include "zigzagwipe.hxx"
+
+
+namespace slideshow {
+namespace internal {
+
+ZigZagWipe::ZigZagWipe( sal_Int32 nZigs ) : m_zigEdge( 1.0 / nZigs )
+{
+ const double d = m_zigEdge;
+ const double d2 = (d / 2.0);
+ m_stdZigZag.append( ::basegfx::B2DPoint( -1.0 - d, -d ) );
+ m_stdZigZag.append( ::basegfx::B2DPoint( -1.0 - d, 1.0 + d ) );
+ m_stdZigZag.append( ::basegfx::B2DPoint( -d, 1.0 + d ) );
+ for ( sal_Int32 pos = (nZigs + 2); pos--; ) {
+ m_stdZigZag.append( ::basegfx::B2DPoint( 0.0, ((pos - 1) * d) + d2 ) );
+ m_stdZigZag.append( ::basegfx::B2DPoint( -d, (pos - 1) * d ) );
+ }
+ m_stdZigZag.setClosed(true);
+}
+
+::basegfx::B2DPolyPolygon ZigZagWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res(m_stdZigZag);
+ res.transform(basegfx::tools::createTranslateB2DHomMatrix((1.0 + m_zigEdge) * t, 0.0));
+ return res;
+}
+
+::basegfx::B2DPolyPolygon BarnZigZagWipe::operator () ( double t )
+{
+ ::basegfx::B2DPolyPolygon res( createUnitRect() );
+ ::basegfx::B2DPolygon poly( m_stdZigZag );
+ poly.flip();
+ basegfx::B2DHomMatrix aTransform(basegfx::tools::createTranslateB2DHomMatrix(
+ (1.0 + m_zigEdge) * (1.0 - t) / 2.0, 0.0));
+ poly.transform( aTransform );
+ res.append( poly );
+ aTransform.scale( -1.0, 1.0 );
+ aTransform.translate( 1.0, m_zigEdge / 2.0 );
+ poly = m_stdZigZag;
+ poly.transform( aTransform );
+ res.append( poly );
+ return res;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/transitions/zigzagwipe.hxx b/slideshow/source/engine/transitions/zigzagwipe.hxx
new file mode 100644
index 000000000000..8126890119fb
--- /dev/null
+++ b/slideshow/source/engine/transitions/zigzagwipe.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_ZIGZAGWIPE_HXX
+#define INCLUDED_SLIDESHOW_ZIGZAGWIPE_HXX
+
+#include "parametricpolypolygon.hxx"
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+
+namespace slideshow {
+namespace internal {
+
+/// Generates a left to right zigZag wipe:
+class ZigZagWipe : public ParametricPolyPolygon
+{
+public:
+ ZigZagWipe( sal_Int32 nZigs );
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+protected:
+ const double m_zigEdge;
+ ::basegfx::B2DPolygon m_stdZigZag;
+};
+
+/// Generates a vertical barnZigZag wipe:
+class BarnZigZagWipe : public ZigZagWipe
+{
+public:
+ BarnZigZagWipe( sal_Int32 nZigs ) : ZigZagWipe(nZigs) {}
+ virtual ::basegfx::B2DPolyPolygon operator () ( double t );
+};
+
+}
+}
+
+#endif /* INCLUDED_SLIDESHOW_ZIGZAGWIPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/unoviewcontainer.cxx b/slideshow/source/engine/unoviewcontainer.cxx
new file mode 100644
index 000000000000..a5db2abd4ab2
--- /dev/null
+++ b/slideshow/source/engine/unoviewcontainer.cxx
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <canvas/debug.hxx>
+#include <unoviewcontainer.hxx>
+
+#include <boost/bind.hpp>
+
+#include <algorithm>
+
+
+using namespace ::com::sun::star;
+
+// -----------------------------------------------------------------------------
+
+namespace slideshow
+{
+ namespace internal
+ {
+ UnoViewContainer::UnoViewContainer() :
+ maViews()
+ {
+ }
+
+ bool UnoViewContainer::addView( const UnoViewSharedPtr& rView )
+ {
+ // check whether same view is already added
+ const UnoViewVector::iterator aEnd( maViews.end() );
+
+ // already added?
+ if( ::std::find_if( maViews.begin(),
+ aEnd,
+ ::boost::bind(
+ ::std::equal_to< uno::Reference< presentation::XSlideShowView > >(),
+ ::boost::cref( rView->getUnoView() ),
+ ::boost::bind(
+ &UnoView::getUnoView,
+ _1 ) ) ) != aEnd )
+ {
+ // yes, nothing to do
+ return false;
+ }
+
+ // add locally
+ maViews.push_back( rView );
+
+ return true;
+ }
+
+ UnoViewSharedPtr UnoViewContainer::removeView( const uno::Reference< presentation::XSlideShowView >& xView )
+ {
+ // check whether same view is already added
+ const UnoViewVector::iterator aEnd( maViews.end() );
+ UnoViewVector::iterator aIter;
+
+ // added in the first place?
+ if( (aIter=::std::find_if( maViews.begin(),
+ aEnd,
+ ::boost::bind(
+ ::std::equal_to< uno::Reference< presentation::XSlideShowView > >(),
+ ::boost::cref( xView ),
+ ::boost::bind(
+ &UnoView::getUnoView,
+ _1 ) ) ) ) == aEnd )
+ {
+ // nope, nothing to do
+ return UnoViewSharedPtr();
+ }
+
+ OSL_ENSURE(
+ ::std::count_if(
+ maViews.begin(),
+ aEnd,
+ ::boost::bind(
+ ::std::equal_to< uno::Reference< presentation::XSlideShowView > >(),
+ ::boost::cref( xView ),
+ ::boost::bind(
+ &UnoView::getUnoView,
+ _1 ))) == 1,
+ "UnoViewContainer::removeView(): View was added multiple times" );
+
+ UnoViewSharedPtr pView( *aIter );
+
+ // actually erase from container
+ maViews.erase( aIter );
+
+ return pView;
+ }
+
+ bool UnoViewContainer::removeView( const UnoViewSharedPtr& rView )
+ {
+ // remove locally
+ const UnoViewVector::iterator aEnd( maViews.end() );
+ UnoViewVector::iterator aIter;
+ if( (aIter=::std::find( maViews.begin(),
+ aEnd,
+ rView )) == aEnd )
+ {
+ // view seemingly was not added, failed
+ return false;
+ }
+
+ OSL_ENSURE( ::std::count( maViews.begin(),
+ aEnd,
+ rView ) == 1,
+ "UnoViewContainer::removeView(): View was added multiple times" );
+
+ // actually erase from container
+ maViews.erase( aIter );
+
+ return true;
+ }
+
+ void UnoViewContainer::dispose()
+ {
+ ::std::for_each( maViews.begin(),
+ maViews.end(),
+ ::boost::mem_fn(&UnoView::_dispose) );
+ maViews.clear();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/usereventqueue.cxx b/slideshow/source/engine/usereventqueue.cxx
new file mode 100644
index 000000000000..48b588a73c32
--- /dev/null
+++ b/slideshow/source/engine/usereventqueue.cxx
@@ -0,0 +1,1009 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/awt/MouseEvent.hpp>
+
+#include <boost/bind.hpp>
+
+#include "delayevent.hxx"
+#include "usereventqueue.hxx"
+#include "cursormanager.hxx"
+#include "slideshowexceptions.hxx"
+
+#include <vector>
+#include <queue>
+#include <map>
+#include <functional>
+#include <algorithm>
+
+
+using namespace com::sun::star;
+
+/* Implementation of UserEventQueue class */
+
+namespace slideshow {
+namespace internal {
+
+namespace {
+
+typedef std::vector<EventSharedPtr> ImpEventVector;
+typedef std::queue<EventSharedPtr> ImpEventQueue;
+typedef std::map<uno::Reference<animations::XAnimationNode>,
+ ImpEventVector> ImpAnimationEventMap;
+typedef std::map<ShapeSharedPtr, ImpEventQueue,
+ Shape::lessThanShape> ImpShapeEventMap;
+
+// MouseEventHandler base class, not consuming any event:
+class MouseEventHandler_ : public MouseEventHandler
+{
+public:
+ virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) { return false;}
+ virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) { return false;}
+ virtual bool handleMouseEntered( awt::MouseEvent const& /*e*/ ) { return false;}
+ virtual bool handleMouseExited( awt::MouseEvent const& /*e*/ ) { return false; }
+ virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) { return false;}
+ virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) { return false; }
+};
+
+/** @return one event has been posted
+ */
+template <typename ContainerT>
+bool fireSingleEvent( ContainerT & rQueue, EventQueue & rEventQueue )
+{
+ // post next event in given queue:
+ while (! rQueue.empty())
+ {
+ EventSharedPtr const pEvent(rQueue.front());
+ rQueue.pop();
+
+ // skip all inactive events (as the purpose of
+ // nextEventFromQueue() is to activate the next
+ // event, and events which return false on
+ // isCharged() will never be activated by the
+ // EventQueue)
+ if(pEvent->isCharged())
+ return rEventQueue.addEvent( pEvent );
+ }
+ return false; // no more (active) events in queue
+}
+
+/** @return at least one event has been posted
+ */
+template <typename ContainerT>
+bool fireAllEvents( ContainerT & rQueue, EventQueue & rEventQueue )
+{
+ bool bFiredAny = false;
+ while (fireSingleEvent( rQueue, rEventQueue ))
+ bFiredAny = true;
+ return bFiredAny;
+}
+
+class EventContainer
+{
+public:
+ EventContainer() :
+ maEvents()
+ {}
+
+ void clearContainer()
+ {
+ maEvents = ImpEventQueue();
+ }
+
+ void addEvent( const EventSharedPtr& rEvent )
+ {
+ maEvents.push( rEvent );
+ }
+
+ bool isEmpty()
+ {
+ return maEvents.empty();
+ }
+
+protected:
+ ImpEventQueue maEvents;
+};
+
+} // anon namespace
+
+class PlainEventHandler : public EventHandler,
+ public EventContainer
+{
+public:
+ PlainEventHandler( EventQueue & rEventQueue )
+ : EventContainer(), mrEventQueue(rEventQueue) {}
+
+ virtual void dispose()
+ {
+ clearContainer();
+ }
+
+ virtual bool handleEvent()
+ {
+ return fireAllEvents( maEvents, mrEventQueue );
+ }
+
+private:
+ EventQueue & mrEventQueue;
+};
+
+class AllAnimationEventHandler : public AnimationEventHandler
+{
+public:
+ AllAnimationEventHandler( EventQueue& rEventQueue ) :
+ mrEventQueue( rEventQueue ),
+ maAnimationEventMap()
+ {}
+
+ virtual void dispose()
+ {
+ maAnimationEventMap.clear();
+ }
+
+ virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
+ {
+ ENSURE_OR_RETURN_FALSE(
+ rNode,
+ "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
+
+ bool bRet( false );
+
+ ImpAnimationEventMap::iterator aIter;
+ if( (aIter=maAnimationEventMap.find(
+ rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
+ {
+ ImpEventVector& rVec( aIter->second );
+
+ bRet = !rVec.empty();
+
+ // registered node found -> fire all events in the vector
+ std::for_each( rVec.begin(), rVec.end(),
+ boost::bind( &EventQueue::addEvent,
+ boost::ref( mrEventQueue ), _1 ) );
+
+ rVec.clear();
+ }
+
+ return bRet;
+ }
+
+ void addEvent( const EventSharedPtr& rEvent,
+ const uno::Reference< animations::XAnimationNode >& xNode )
+ {
+ ImpAnimationEventMap::iterator aIter;
+ if( (aIter=maAnimationEventMap.find( xNode )) ==
+ maAnimationEventMap.end() )
+ {
+ // no entry for this animation -> create one
+ aIter = maAnimationEventMap.insert(
+ ImpAnimationEventMap::value_type( xNode,
+ ImpEventVector() ) ).first;
+ }
+
+ // add new event to queue
+ aIter->second.push_back( rEvent );
+ }
+
+ bool isEmpty()
+ {
+ // find at least one animation with a non-empty vector
+ ImpAnimationEventMap::const_iterator aCurr( maAnimationEventMap.begin() );
+ const ImpAnimationEventMap::const_iterator aEnd( maAnimationEventMap.end() );
+ while( aCurr != aEnd )
+ {
+ if( !aCurr->second.empty() )
+ return false; // at least one non-empty entry found
+
+ ++aCurr;
+ }
+
+ return true; // not a single non-empty entry found
+ }
+
+private:
+ EventQueue& mrEventQueue;
+ ImpAnimationEventMap maAnimationEventMap;
+};
+
+class ClickEventHandler : public MouseEventHandler_,
+ public EventHandler,
+ public EventContainer
+{
+public:
+ ClickEventHandler( EventQueue& rEventQueue ) :
+ EventContainer(),
+ mrEventQueue( rEventQueue ),
+ mbAdvanceOnClick( true )
+ {}
+
+ void setAdvanceOnClick( bool bAdvanceOnClick )
+ {
+ mbAdvanceOnClick = bAdvanceOnClick;
+ }
+
+private:
+ virtual void dispose()
+ {
+ clearContainer();
+ }
+
+ // triggered by API calls, e.g. space bar
+ virtual bool handleEvent()
+ {
+ return handleEvent_impl();
+ }
+
+ // triggered by mouse release:
+ virtual bool handleMouseReleased( const awt::MouseEvent& evt )
+ {
+ if(evt.Buttons != awt::MouseButton::LEFT)
+ return false;
+
+ if( mbAdvanceOnClick ) {
+ // fire next event
+ return handleEvent_impl();
+ }
+ else {
+ return false; // advance-on-click disabled
+ }
+ }
+
+ // triggered by both:
+ virtual bool handleEvent_impl()
+ {
+ // fire next event:
+ return fireSingleEvent( maEvents, mrEventQueue );
+ }
+
+private:
+ EventQueue& mrEventQueue;
+ bool mbAdvanceOnClick;
+};
+
+class SkipEffectEventHandler : public ClickEventHandler
+{
+public:
+ SkipEffectEventHandler( EventQueue & rEventQueue,
+ EventMultiplexer & rEventMultiplexer )
+ : ClickEventHandler(rEventQueue),
+ mrEventQueue(rEventQueue),
+ mrEventMultiplexer(rEventMultiplexer),
+ mbSkipTriggersNextEffect(true) {}
+
+ /** Remember to trigger (or not to trigger) the next effect after the
+ current effect is skiped.
+ */
+ void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
+ { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }
+
+ /// Skip the current effect but do not triggere the next effect.
+ void skipEffect (void) { handleEvent_impl(false); }
+
+private:
+ virtual bool handleEvent_impl()
+ {
+ return handleEvent_impl(true);
+ }
+
+ bool handleEvent_impl (bool bNotifyNextEffect)
+ {
+ // fire all events, so animation nodes can register their
+ // next effect listeners:
+ if(fireAllEvents( maEvents, mrEventQueue ))
+ {
+ if (mbSkipTriggersNextEffect && bNotifyNextEffect)
+ {
+ // then simulate a next effect event: this skip effect
+ // handler is triggered upon next effect events (multiplexer
+ // prio=-1)! Posting a notifyNextEffect() here is only safe
+ // (we don't run into busy loop), because we assume that
+ // someone has registerered above for next effects
+ // (multiplexer prio=0) at the user event queue.
+ return mrEventQueue.addEventWhenQueueIsEmpty(
+ makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect,
+ boost::ref(mrEventMultiplexer) ),
+ "EventMultiplexer::notifyNextEffect") );
+ }
+ else
+ return true;
+ }
+ return false;
+ }
+
+private:
+ EventQueue & mrEventQueue;
+ EventMultiplexer & mrEventMultiplexer;
+ bool mbSkipTriggersNextEffect;
+};
+
+class RewindEffectEventHandler : public MouseEventHandler_,
+ public EventContainer
+{
+public:
+ RewindEffectEventHandler( EventQueue & rEventQueue )
+ : EventContainer(), mrEventQueue(rEventQueue) {}
+
+private:
+ virtual void dispose()
+ {
+ clearContainer();
+ }
+
+ virtual bool handleMouseReleased( awt::MouseEvent const& evt )
+ {
+ if(evt.Buttons != awt::MouseButton::RIGHT)
+ return false;
+
+ return fireAllEvents( maEvents, mrEventQueue );
+ }
+
+private:
+ EventQueue & mrEventQueue;
+};
+
+/** Base class to share some common code between
+ ShapeClickEventHandler and MouseMoveHandler
+
+ @derive override necessary MouseEventHandler interface methods,
+ call sendEvent() method to actually process the event.
+*/
+class MouseHandlerBase : public MouseEventHandler_
+{
+public:
+ MouseHandlerBase( EventQueue& rEventQueue ) :
+ mrEventQueue( rEventQueue ),
+ maShapeEventMap()
+ {}
+
+ virtual void dispose()
+ {
+ // TODO(Q1): Check whether plain vector with swap idiom is
+ // okay here
+ maShapeEventMap = ImpShapeEventMap();
+ }
+
+ void addEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape )
+ {
+ ImpShapeEventMap::iterator aIter;
+ if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
+ {
+ // no entry for this shape -> create one
+ aIter = maShapeEventMap.insert(
+ ImpShapeEventMap::value_type( rShape,
+ ImpEventQueue() ) ).first;
+ }
+
+ // add new event to queue
+ aIter->second.push( rEvent );
+ }
+
+ bool isEmpty()
+ {
+ // find at least one shape with a non-empty queue
+ ImpShapeEventMap::reverse_iterator aCurrShape( maShapeEventMap.begin());
+ ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.end() );
+ while( aCurrShape != aEndShape )
+ {
+ if( !aCurrShape->second.empty() )
+ return false; // at least one non-empty entry found
+
+ ++aCurrShape;
+ }
+
+ return true; // not a single non-empty entry found
+ }
+
+protected:
+ bool hitTest( const awt::MouseEvent& e,
+ ImpShapeEventMap::reverse_iterator& o_rHitShape )
+ {
+ // find hit shape in map
+ const basegfx::B2DPoint aPosition( e.X, e.Y );
+
+ // find matching shape (scan reversely, to coarsely match
+ // paint order)
+ ImpShapeEventMap::reverse_iterator aCurrShape(maShapeEventMap.rbegin());
+ const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() );
+ while( aCurrShape != aEndShape )
+ {
+ // TODO(F2): Get proper geometry polygon from the
+ // shape, to avoid having areas outside the shape
+ // react on the mouse
+ if( aCurrShape->first->getBounds().isInside( aPosition ) &&
+ aCurrShape->first->isVisible() )
+ {
+ // shape hit, and shape is visible - report a
+ // hit
+ o_rHitShape = aCurrShape;
+ return true;
+ }
+
+ ++aCurrShape;
+ }
+
+ return false; // nothing hit
+ }
+
+ bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape )
+ {
+ // take next event from queue
+ const bool bRet( fireSingleEvent( io_rHitShape->second,
+ mrEventQueue ) );
+
+ // clear shape entry, if its queue is
+ // empty. This is important, since the shapes
+ // are held by shared ptr, and might otherwise
+ // not get released, even after their owning
+ // slide is long gone.
+ if( io_rHitShape->second.empty() )
+ {
+ // this looks funny, since ::std::map does
+ // provide an erase( iterator )
+ // method. Unfortunately, stlport does not
+ // declare the obvious erase(
+ // reverse_iterator ) needed here (missing
+ // orthogonality, eh?)
+ maShapeEventMap.erase( io_rHitShape->first );
+ }
+
+ return bRet;
+ }
+
+ bool processEvent( const awt::MouseEvent& e )
+ {
+ ImpShapeEventMap::reverse_iterator aCurrShape;
+
+ if( hitTest( e, aCurrShape ) )
+ return sendEvent( aCurrShape );
+
+ return false; // did not handle the event
+ }
+
+private:
+ EventQueue& mrEventQueue;
+ ImpShapeEventMap maShapeEventMap;
+};
+
+class ShapeClickEventHandler : public MouseHandlerBase
+{
+public:
+ ShapeClickEventHandler( CursorManager& rCursorManager,
+ EventQueue& rEventQueue ) :
+ MouseHandlerBase( rEventQueue ),
+ mrCursorManager( rCursorManager )
+ {}
+
+ virtual bool handleMouseReleased( const awt::MouseEvent& e )
+ {
+ if(e.Buttons != awt::MouseButton::LEFT)
+ return false;
+ return processEvent( e );
+ }
+
+ virtual bool handleMouseMoved( const awt::MouseEvent& e )
+ {
+ // TODO(P2): Maybe buffer last shape touched
+
+ // if we have a shape click event, and the mouse
+ // hovers over this shape, change cursor to hand
+ ImpShapeEventMap::reverse_iterator aDummy;
+ if( hitTest( e, aDummy ) )
+ mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );
+
+ return false; // we don't /eat/ this event. Lower prio
+ // handler should see it, too.
+ }
+
+private:
+ CursorManager& mrCursorManager;
+};
+
+class MouseEnterHandler : public MouseHandlerBase
+{
+public:
+ MouseEnterHandler( EventQueue& rEventQueue )
+ : MouseHandlerBase( rEventQueue ),
+ mpLastShape() {}
+
+ virtual bool handleMouseMoved( const awt::MouseEvent& e )
+ {
+ // TODO(P2): Maybe buffer last shape touched, and
+ // check against that _first_
+
+ ImpShapeEventMap::reverse_iterator aCurr;
+ if( hitTest( e, aCurr ) )
+ {
+ if( aCurr->first != mpLastShape )
+ {
+ // we actually hit a shape, and it's different
+ // from the previous one - thus we just
+ // entered it, raise event
+ sendEvent( aCurr );
+ mpLastShape = aCurr->first;
+ }
+ }
+ else
+ {
+ // don't hit no shape - thus, last shape is NULL
+ mpLastShape.reset();
+ }
+
+ return false; // we don't /eat/ this event. Lower prio
+ // handler should see it, too.
+ }
+
+private:
+ ShapeSharedPtr mpLastShape;
+};
+
+class MouseLeaveHandler : public MouseHandlerBase
+{
+public:
+ MouseLeaveHandler( EventQueue& rEventQueue )
+ : MouseHandlerBase( rEventQueue ),
+ maLastIter() {}
+
+ virtual bool handleMouseMoved( const awt::MouseEvent& e )
+ {
+ // TODO(P2): Maybe buffer last shape touched, and
+ // check against that _first_
+
+ ImpShapeEventMap::reverse_iterator aCurr;
+ if( hitTest( e, aCurr ) )
+ {
+ maLastIter = aCurr;
+ }
+ else
+ {
+ if( maLastIter->first )
+ {
+ // last time, we were over a shape, now we're
+ // not - we thus just left that shape, raise
+ // event
+ sendEvent( maLastIter );
+ }
+
+ // in any case, when we hit this else-branch: no
+ // shape hit, thus have to clear maLastIter
+ maLastIter = ImpShapeEventMap::reverse_iterator();
+ }
+
+ return false; // we don't /eat/ this event. Lower prio
+ // handler should see it, too.
+ }
+
+private:
+ ImpShapeEventMap::reverse_iterator maLastIter;
+};
+
+template< typename Handler, typename Functor >
+void UserEventQueue::registerEvent(
+ boost::shared_ptr< Handler >& rHandler,
+ const EventSharedPtr& rEvent,
+ const Functor& rRegistrationFunctor )
+{
+ ENSURE_OR_THROW( rEvent,
+ "UserEventQueue::registerEvent(): Invalid event" );
+
+ if( !rHandler ) {
+ // create handler
+ rHandler.reset( new Handler( mrEventQueue ) );
+ // register handler on EventMultiplexer
+ rRegistrationFunctor( rHandler );
+ }
+
+ rHandler->addEvent( rEvent );
+}
+
+template< typename Handler, typename Arg, typename Functor >
+void UserEventQueue::registerEvent(
+ boost::shared_ptr< Handler >& rHandler,
+ const EventSharedPtr& rEvent,
+ const Arg& rArg,
+ const Functor& rRegistrationFunctor )
+{
+ ENSURE_OR_THROW( rEvent,
+ "UserEventQueue::registerEvent(): Invalid event" );
+
+ if( !rHandler ) {
+ // create handler
+ rHandler.reset( new Handler( mrEventQueue ) );
+
+ // register handler on EventMultiplexer
+ rRegistrationFunctor( rHandler );
+ }
+
+ rHandler->addEvent( rEvent, rArg );
+}
+
+
+// Public methods
+// =====================================================
+
+UserEventQueue::UserEventQueue( EventMultiplexer& rMultiplexer,
+ EventQueue& rEventQueue,
+ CursorManager& rCursorManager )
+ : mrMultiplexer( rMultiplexer ),
+ mrEventQueue( rEventQueue ),
+ mrCursorManager( rCursorManager ),
+ mpStartEventHandler(),
+ mpEndEventHandler(),
+ mpAnimationStartEventHandler(),
+ mpAnimationEndEventHandler(),
+ mpAudioStoppedEventHandler(),
+ mpClickEventHandler(),
+ mpSkipEffectEventHandler(),
+ mpRewindEffectEventHandler(),
+ mpDoubleClickEventHandler(),
+ mpMouseEnterHandler(),
+ mpMouseLeaveHandler(),
+ mbAdvanceOnClick( true )
+{
+}
+
+UserEventQueue::~UserEventQueue()
+{
+ try
+ {
+ // unregister all handlers
+ clear();
+ }
+ catch (uno::Exception &) {
+ OSL_ENSURE( false, rtl::OUStringToOString(
+ comphelper::anyToString(
+ cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+}
+
+bool UserEventQueue::isEmpty() const
+{
+ // TODO(T2): This is not thread safe, the handlers are all
+ // only separately synchronized. This poses the danger of
+ // generating false empty status on XSlideShow::update(), such
+ // that the last events of a slide are not triggered.
+
+ // we're empty iff all handler queues are empty
+ return
+ (mpStartEventHandler ? mpStartEventHandler->isEmpty() : true) &&
+ (mpEndEventHandler ? mpEndEventHandler->isEmpty() : true) &&
+ (mpAnimationStartEventHandler ? mpAnimationStartEventHandler->isEmpty() : true) &&
+ (mpAnimationEndEventHandler ? mpAnimationEndEventHandler->isEmpty() : true) &&
+ (mpAudioStoppedEventHandler ? mpAudioStoppedEventHandler->isEmpty() : true) &&
+ (mpShapeClickEventHandler ? mpShapeClickEventHandler->isEmpty() : true) &&
+ (mpClickEventHandler ? mpClickEventHandler->isEmpty() : true) &&
+ (mpSkipEffectEventHandler ? mpSkipEffectEventHandler->isEmpty() : true) &&
+ (mpRewindEffectEventHandler ? mpRewindEffectEventHandler->isEmpty() : true) &&
+ (mpShapeDoubleClickEventHandler ? mpShapeDoubleClickEventHandler->isEmpty() : true) &&
+ (mpDoubleClickEventHandler ? mpDoubleClickEventHandler->isEmpty() : true) &&
+ (mpMouseEnterHandler ? mpMouseEnterHandler->isEmpty() : true) &&
+ (mpMouseLeaveHandler ? mpMouseLeaveHandler->isEmpty() : true);
+}
+
+void UserEventQueue::clear()
+{
+ // unregister and delete all handlers
+ if( mpStartEventHandler ) {
+ mrMultiplexer.removeSlideStartHandler( mpStartEventHandler );
+ mpStartEventHandler.reset();
+ }
+ if( mpEndEventHandler ) {
+ mrMultiplexer.removeSlideEndHandler( mpEndEventHandler );
+ mpEndEventHandler.reset();
+ }
+ if( mpAnimationStartEventHandler ) {
+ mrMultiplexer.removeAnimationStartHandler(
+ mpAnimationStartEventHandler );
+ mpAnimationStartEventHandler.reset();
+ }
+ if( mpAnimationEndEventHandler ) {
+ mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
+ mpAnimationEndEventHandler.reset();
+ }
+ if( mpAudioStoppedEventHandler ) {
+ mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
+ mpAudioStoppedEventHandler.reset();
+ }
+ if( mpShapeClickEventHandler ) {
+ mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
+ mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
+ mpShapeClickEventHandler.reset();
+ }
+ if( mpClickEventHandler ) {
+ mrMultiplexer.removeClickHandler( mpClickEventHandler );
+ mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
+ mpClickEventHandler.reset();
+ }
+ if(mpSkipEffectEventHandler) {
+ mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
+ mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
+ mpSkipEffectEventHandler.reset();
+ }
+ if(mpRewindEffectEventHandler) {
+ mrMultiplexer.removeClickHandler( mpRewindEffectEventHandler );
+ mpRewindEffectEventHandler.reset();
+ }
+ if( mpShapeDoubleClickEventHandler ) {
+ mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
+ mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
+ mpShapeDoubleClickEventHandler.reset();
+ }
+ if( mpDoubleClickEventHandler ) {
+ mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler );
+ mpDoubleClickEventHandler.reset();
+ }
+ if( mpMouseEnterHandler ) {
+ mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
+ mpMouseEnterHandler.reset();
+ }
+ if( mpMouseLeaveHandler ) {
+ mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
+ mpMouseLeaveHandler.reset();
+ }
+}
+
+void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
+{
+ mbAdvanceOnClick = bAdvanceOnClick;
+
+ // forward to handler, if existing. Otherwise, the handler
+ // creation will do the forwarding.
+ if( mpClickEventHandler )
+ mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
+}
+
+
+void UserEventQueue::registerSlideStartEvent( const EventSharedPtr& rEvent )
+{
+ registerEvent( mpStartEventHandler,
+ rEvent,
+ boost::bind( &EventMultiplexer::addSlideStartHandler,
+ boost::ref( mrMultiplexer ), _1 ) );
+}
+
+void UserEventQueue::registerSlideEndEvent( const EventSharedPtr& rEvent )
+{
+ registerEvent( mpEndEventHandler,
+ rEvent,
+ boost::bind( &EventMultiplexer::addSlideEndHandler,
+ boost::ref( mrMultiplexer ), _1 ) );
+}
+
+void UserEventQueue::registerAnimationStartEvent(
+ const EventSharedPtr& rEvent,
+ const uno::Reference< animations::XAnimationNode>& xNode )
+{
+ registerEvent( mpAnimationStartEventHandler,
+ rEvent,
+ xNode,
+ boost::bind( &EventMultiplexer::addAnimationStartHandler,
+ boost::ref( mrMultiplexer ), _1 ) );
+}
+
+void UserEventQueue::registerAnimationEndEvent(
+ const EventSharedPtr& rEvent,
+ const uno::Reference<animations::XAnimationNode>& xNode )
+{
+ registerEvent( mpAnimationEndEventHandler,
+ rEvent,
+ xNode,
+ boost::bind( &EventMultiplexer::addAnimationEndHandler,
+ boost::ref( mrMultiplexer ), _1 ) );
+}
+
+void UserEventQueue::registerAudioStoppedEvent(
+ const EventSharedPtr& rEvent,
+ const uno::Reference<animations::XAnimationNode>& xNode )
+{
+ registerEvent( mpAudioStoppedEventHandler,
+ rEvent,
+ xNode,
+ boost::bind( &EventMultiplexer::addAudioStoppedHandler,
+ boost::ref( mrMultiplexer ), _1 ) );
+}
+
+void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape )
+{
+ ENSURE_OR_THROW(
+ rEvent,
+ "UserEventQueue::registerShapeClickEvent(): Invalid event" );
+
+ if( !mpShapeClickEventHandler )
+ {
+ // create handler
+ mpShapeClickEventHandler.reset(
+ new ShapeClickEventHandler(mrCursorManager,
+ mrEventQueue) );
+
+ // register handler on EventMultiplexer
+ mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
+ mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
+ }
+
+ mpShapeClickEventHandler->addEvent( rEvent, rShape );
+}
+
+namespace {
+class ClickEventRegistrationFunctor
+{
+public:
+ ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
+ double nPrio,
+ bool bAdvanceOnClick )
+ : mrMultiplexer( rMultiplexer ),
+ mnPrio(nPrio),
+ mbAdvanceOnClick( bAdvanceOnClick ) {}
+
+ void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const
+ {
+ // register the handler on _two_ sources: we want the
+ // nextEffect events, e.g. space bar, to trigger clicks, as well!
+ mrMultiplexer.addClickHandler( rHandler, mnPrio );
+ mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );
+
+ // forward advance-on-click state to newly
+ // generated handler (that's the only reason why
+ // we're called here)
+ rHandler->setAdvanceOnClick( mbAdvanceOnClick );
+ }
+
+private:
+ EventMultiplexer& mrMultiplexer;
+ double const mnPrio;
+ bool const mbAdvanceOnClick;
+};
+} // anon namespace
+
+void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
+{
+ // TODO: better name may be mpNextEffectEventHandler? then we have
+ // next effect (=> waiting to be started)
+ // skip effect (skipping the currently running one)
+ // rewind effect (rewinding back running one and waiting (again)
+ // to be started)
+ registerEvent( mpClickEventHandler,
+ rEvent,
+ ClickEventRegistrationFunctor( mrMultiplexer,
+ 0.0 /* default prio */,
+ mbAdvanceOnClick ) );
+}
+
+void UserEventQueue::registerSkipEffectEvent(
+ EventSharedPtr const & pEvent,
+ const bool bSkipTriggersNextEffect)
+{
+ if(!mpSkipEffectEventHandler)
+ {
+ mpSkipEffectEventHandler.reset(
+ new SkipEffectEventHandler( mrEventQueue, mrMultiplexer ) );
+ // register the handler on _two_ sources: we want the
+ // nextEffect events, e.g. space bar, to trigger clicks, as well!
+ mrMultiplexer.addClickHandler( mpSkipEffectEventHandler,
+ -1.0 /* prio below default */ );
+ mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
+ -1.0 /* prio below default */ );
+ // forward advance-on-click state to newly
+ // generated handler (that's the only reason why
+ // we're called here)
+ mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
+ }
+ mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
+ mpSkipEffectEventHandler->addEvent( pEvent );
+}
+
+void UserEventQueue::registerRewindEffectEvent( EventSharedPtr const& pEvent )
+{
+ registerEvent( mpRewindEffectEventHandler,
+ pEvent,
+ boost::bind( &EventMultiplexer::addClickHandler,
+ boost::ref(mrMultiplexer), _1,
+ -1.0 /* prio below default */ ) );
+}
+
+void UserEventQueue::registerShapeDoubleClickEvent(
+ const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape )
+{
+ ENSURE_OR_THROW(
+ rEvent,
+ "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
+
+ if( !mpShapeDoubleClickEventHandler )
+ {
+ // create handler
+ mpShapeDoubleClickEventHandler.reset(
+ new ShapeClickEventHandler(mrCursorManager,
+ mrEventQueue) );
+
+ // register handler on EventMultiplexer
+ mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
+ 1.0 );
+ mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
+ 1.0 );
+ }
+
+ mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
+}
+
+void UserEventQueue::registerDoubleClickEvent( const EventSharedPtr& rEvent )
+{
+ registerEvent( mpDoubleClickEventHandler,
+ rEvent,
+ boost::bind( &EventMultiplexer::addDoubleClickHandler,
+ boost::ref( mrMultiplexer ), _1,
+ 0.0 /* default prio */ ) );
+}
+
+void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape )
+{
+ registerEvent( mpMouseEnterHandler,
+ rEvent,
+ rShape,
+ boost::bind( &EventMultiplexer::addMouseMoveHandler,
+ boost::ref( mrMultiplexer ), _1,
+ 0.0 /* default prio */ ) );
+}
+
+void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape )
+{
+ registerEvent( mpMouseLeaveHandler,
+ rEvent,
+ rShape,
+ boost::bind( &EventMultiplexer::addMouseMoveHandler,
+ boost::ref( mrMultiplexer ), _1,
+ 0.0 /* default prio */ ) );
+}
+
+void UserEventQueue::callSkipEffectEventHandler (void)
+{
+ ::boost::shared_ptr<SkipEffectEventHandler> pHandler (
+ ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
+ if (pHandler)
+ pHandler->skipEffect();
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/waitsymbol.cxx b/slideshow/source/engine/waitsymbol.cxx
new file mode 100644
index 000000000000..8e36df48775a
--- /dev/null
+++ b/slideshow/source/engine/waitsymbol.cxx
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+#include <boost/current_function.hpp>
+#include <canvas/canvastools.hxx>
+
+#include <comphelper/anytostring.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+
+#include <com/sun/star/rendering/XCanvas.hpp>
+
+#include "waitsymbol.hxx"
+#include "eventmultiplexer.hxx"
+
+#include <algorithm>
+
+
+using namespace com::sun::star;
+
+namespace slideshow {
+namespace internal {
+
+const sal_Int32 LEFT_BORDER_SPACE = 10;
+const sal_Int32 LOWER_BORDER_SPACE = 10;
+
+WaitSymbolSharedPtr WaitSymbol::create( const uno::Reference<rendering::XBitmap>& xBitmap,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const UnoViewContainer& rViewContainer )
+{
+ WaitSymbolSharedPtr pRet(
+ new WaitSymbol( xBitmap,
+ rScreenUpdater,
+ rViewContainer ));
+
+ rEventMultiplexer.addViewHandler( pRet );
+
+ return pRet;
+}
+
+WaitSymbol::WaitSymbol( uno::Reference<rendering::XBitmap> const & xBitmap,
+ ScreenUpdater& rScreenUpdater,
+ const UnoViewContainer& rViewContainer ) :
+ mxBitmap(xBitmap),
+ maViews(),
+ mrScreenUpdater( rScreenUpdater ),
+ mbVisible(false)
+{
+ std::for_each( rViewContainer.begin(),
+ rViewContainer.end(),
+ boost::bind( &WaitSymbol::viewAdded,
+ this,
+ _1 ));
+}
+
+void WaitSymbol::setVisible( const bool bVisible )
+{
+ if( mbVisible != bVisible )
+ {
+ mbVisible = bVisible;
+
+ ViewsVecT::const_iterator aIter( maViews.begin() );
+ ViewsVecT::const_iterator const aEnd ( maViews.end() );
+ while( aIter != aEnd )
+ {
+ if( aIter->second )
+ {
+ if( bVisible )
+ aIter->second->show();
+ else
+ aIter->second->hide();
+ }
+
+ ++aIter;
+ }
+
+ // sprites changed, need a screen update for this frame.
+ mrScreenUpdater.requestImmediateUpdate();
+ }
+}
+
+basegfx::B2DPoint WaitSymbol::calcSpritePos(
+ UnoViewSharedPtr const & rView ) const
+{
+ const uno::Reference<rendering::XBitmap> xBitmap( rView->getCanvas()->getUNOCanvas(),
+ uno::UNO_QUERY_THROW );
+ const geometry::IntegerSize2D realSize( xBitmap->getSize() );
+ return basegfx::B2DPoint(
+ std::min<sal_Int32>( realSize.Width, LEFT_BORDER_SPACE ),
+ std::max<sal_Int32>( 0, realSize.Height - mxBitmap->getSize().Height
+ - LOWER_BORDER_SPACE ) );
+}
+
+void WaitSymbol::viewAdded( const UnoViewSharedPtr& rView )
+{
+ cppcanvas::CustomSpriteSharedPtr sprite;
+
+ try
+ {
+ const geometry::IntegerSize2D spriteSize( mxBitmap->getSize() );
+ sprite = rView->createSprite( basegfx::B2DVector( spriteSize.Width,
+ spriteSize.Height ),
+ 1000.0 ); // sprite should be in front of all
+ // other sprites
+ rendering::ViewState viewState;
+ canvas::tools::initViewState( viewState );
+ rendering::RenderState renderState;
+ canvas::tools::initRenderState( renderState );
+ sprite->getContentCanvas()->getUNOCanvas()->drawBitmap(
+ mxBitmap, viewState, renderState );
+
+ sprite->setAlpha( 0.9 );
+ sprite->movePixel( calcSpritePos( rView ) );
+ if( mbVisible )
+ sprite->show();
+ }
+ catch( uno::Exception& )
+ {
+ OSL_ENSURE( false,
+ rtl::OUStringToOString(
+ comphelper::anyToString( cppu::getCaughtException() ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+ maViews.push_back( ViewsVecT::value_type( rView, sprite ) );
+}
+
+void WaitSymbol::viewRemoved( const UnoViewSharedPtr& rView )
+{
+ maViews.erase(
+ std::remove_if(
+ maViews.begin(), maViews.end(),
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind( std::select1st<ViewsVecT::value_type>(), _1 ) ) ),
+ maViews.end() );
+}
+
+void WaitSymbol::viewChanged( const UnoViewSharedPtr& rView )
+{
+ // find entry corresponding to modified view
+ ViewsVecT::iterator aModifiedEntry(
+ std::find_if(
+ maViews.begin(),
+ maViews.end(),
+ boost::bind(
+ std::equal_to<UnoViewSharedPtr>(),
+ rView,
+ // select view:
+ boost::bind( std::select1st<ViewsVecT::value_type>(), _1 ))));
+
+ OSL_ASSERT( aModifiedEntry != maViews.end() );
+ if( aModifiedEntry == maViews.end() )
+ return;
+
+ if( aModifiedEntry->second )
+ aModifiedEntry->second->movePixel(
+ calcSpritePos(aModifiedEntry->first) );
+}
+
+void WaitSymbol::viewsChanged()
+{
+ // reposition sprites on all views
+ ViewsVecT::const_iterator aIter( maViews.begin() );
+ ViewsVecT::const_iterator const aEnd ( maViews.end() );
+ while( aIter != aEnd )
+ {
+ if( aIter->second )
+ aIter->second->movePixel(
+ calcSpritePos( aIter->first ));
+ ++aIter;
+ }
+}
+
+} // namespace internal
+} // namespace presentation
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/waitsymbol.hxx b/slideshow/source/engine/waitsymbol.hxx
new file mode 100644
index 000000000000..f23cb2864c7a
--- /dev/null
+++ b/slideshow/source/engine/waitsymbol.hxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined(WAITSYMBOL_HXX_INCLUDED)
+#define WAITSYMBOL_HXX_INCLUDED
+
+#include <com/sun/star/rendering/XBitmap.hpp>
+#include <cppcanvas/customsprite.hxx>
+
+#include "vieweventhandler.hxx"
+#include "screenupdater.hxx"
+#include "eventmultiplexer.hxx"
+#include "unoview.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost/utility.hpp> // for noncopyable
+#include <vector>
+
+namespace slideshow {
+namespace internal {
+
+class EventMultiplexer;
+typedef boost::shared_ptr<class WaitSymbol> WaitSymbolSharedPtr;
+
+class WaitSymbol : public ViewEventHandler,
+ private ::boost::noncopyable
+{
+public:
+ static WaitSymbolSharedPtr create( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap>& xBitmap,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const UnoViewContainer& rViewContainer );
+
+ /** Shows the wait symbol.
+ */
+ void show() { setVisible(true); }
+
+ /** Hides the wait symbol.
+ */
+ void hide() { setVisible(false); }
+
+private:
+ WaitSymbol( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap>& xBitmap,
+ ScreenUpdater& rScreenUpdater,
+ const UnoViewContainer& rViewContainer );
+
+ // ViewEventHandler
+ virtual void viewAdded( const UnoViewSharedPtr& rView );
+ virtual void viewRemoved( const UnoViewSharedPtr& rView );
+ virtual void viewChanged( const UnoViewSharedPtr& rView );
+ virtual void viewsChanged();
+
+ void setVisible( const bool bVisible );
+ ::basegfx::B2DPoint calcSpritePos( UnoViewSharedPtr const & rView ) const;
+
+ template <typename func_type>
+ void for_each_sprite( func_type const & func ) const
+ {
+ ViewsVecT::const_iterator iPos( maViews.begin() );
+ const ViewsVecT::const_iterator iEnd( maViews.end() );
+ for ( ; iPos != iEnd; ++iPos )
+ if( iPos->second )
+ func( iPos->second );
+ }
+
+ typedef ::std::vector<
+ ::std::pair<UnoViewSharedPtr,
+ cppcanvas::CustomSpriteSharedPtr> > ViewsVecT;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap> mxBitmap;
+
+ ViewsVecT maViews;
+ ScreenUpdater& mrScreenUpdater;
+ bool mbVisible;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/wakeupevent.cxx b/slideshow/source/engine/wakeupevent.cxx
new file mode 100644
index 000000000000..9cab96a302f2
--- /dev/null
+++ b/slideshow/source/engine/wakeupevent.cxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <canvas/verbosetrace.hxx>
+
+#include <wakeupevent.hxx>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ WakeupEvent::WakeupEvent(
+ boost::shared_ptr<canvas::tools::ElapsedTime> const & pTimeBase,
+ ActivitiesQueue& rActivityQueue ) :
+#if OSL_DEBUG_LEVEL > 1
+ Event(::rtl::OUString::createFromAscii("WakeupEvent")),
+#endif
+ maTimer(pTimeBase),
+ mnNextTime(0.0),
+ mpActivity(),
+ mrActivityQueue( rActivityQueue )
+ {
+ }
+
+ void WakeupEvent::dispose()
+ {
+ mpActivity.reset();
+ }
+
+ bool WakeupEvent::fire()
+ {
+ if( !mpActivity )
+ return false;
+
+ return mrActivityQueue.addActivity( mpActivity );
+ }
+
+ bool WakeupEvent::isCharged() const
+ {
+ // this event won't expire, we fire everytime we're
+ // re-inserted into the event queue.
+ return true;
+ }
+
+ double WakeupEvent::getActivationTime( double nCurrentTime ) const
+ {
+ const double nElapsedTime( maTimer.getElapsedTime() );
+
+ return ::std::max( nCurrentTime,
+ nCurrentTime - nElapsedTime + mnNextTime );
+ }
+
+ void WakeupEvent::start()
+ {
+ // start timer
+ maTimer.reset();
+ }
+
+ void WakeupEvent::setNextTimeout( double rNextTime )
+ {
+ mnNextTime = rNextTime;
+ }
+
+ void WakeupEvent::setActivity( const ActivitySharedPtr& rActivity )
+ {
+ mpActivity = rActivity;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/activitiesfactory.hxx b/slideshow/source/inc/activitiesfactory.hxx
new file mode 100644
index 000000000000..c32e57720ffc
--- /dev/null
+++ b/slideshow/source/inc/activitiesfactory.hxx
@@ -0,0 +1,336 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ACTIVITIESFACTORY_HXX
+#define INCLUDED_SLIDESHOW_ACTIVITIESFACTORY_HXX
+
+#include <com/sun/star/animations/XAnimate.hpp>
+#include <com/sun/star/animations/XAnimateColor.hpp>
+
+#include "animationactivity.hxx"
+#include "activitiesqueue.hxx"
+#include "event.hxx"
+#include "eventqueue.hxx"
+#include "shape.hxx"
+#include "numberanimation.hxx"
+#include "enumanimation.hxx"
+#include "coloranimation.hxx"
+#include "hslcoloranimation.hxx"
+#include "stringanimation.hxx"
+#include "boolanimation.hxx"
+#include "pairanimation.hxx"
+
+#include <boost/optional.hpp>
+#include <boost/utility.hpp>
+
+/* Definition of ActivitiesFactory class */
+
+namespace slideshow {
+namespace internal {
+
+class ActivitiesFactory : private ::boost::noncopyable
+{
+public:
+ /// Collection of common factory parameters
+ struct CommonParameters
+ {
+ CommonParameters(
+ const EventSharedPtr& rEndEvent,
+ EventQueue& rEventQueue,
+ ActivitiesQueue& rActivitiesQueue,
+ double nMinDuration,
+ sal_uInt32 nMinNumberOfFrames,
+ bool bAutoReverse,
+ ::boost::optional<double> const& aRepeats,
+ double nAcceleration,
+ double nDeceleration,
+ const ShapeSharedPtr& rShape,
+ const ::basegfx::B2DVector& rSlideBounds )
+ : mpEndEvent( rEndEvent ),
+ mrEventQueue( rEventQueue ),
+ mrActivitiesQueue( rActivitiesQueue ),
+ mnMinDuration( nMinDuration ),
+ mnMinNumberOfFrames( nMinNumberOfFrames ),
+ maRepeats( aRepeats ),
+ mnAcceleration( nAcceleration ),
+ mnDeceleration( nDeceleration ),
+ mpShape( rShape ),
+ maSlideBounds( rSlideBounds ),
+ mbAutoReverse( bAutoReverse ) {}
+
+ /// End event to fire when animation is over
+ EventSharedPtr mpEndEvent;
+
+ /// Event queue to insert the end event into.
+ EventQueue& mrEventQueue;
+ /// Event queue to insert the end event into.
+ ActivitiesQueue& mrActivitiesQueue;
+
+ /** Simple duration of the activity
+
+ Specifies the minimal simple duration of the
+ activity (minimal, because mnMinNumberOfFrames
+ might prolongue the activity). According to SMIL,
+ this might also be indefinite, which for our
+ framework does not make much sense, though
+ (wouldn't have a clue, then, how to scale the
+ animation over time).
+ */
+ double mnMinDuration;
+
+ /** Minimal number of frames for this activity.
+
+ This specifies the minimal number of frames this
+ activity will display per simple duration. If less
+ than this number are displayed until mnMinDuration
+ is over, the activity will be prolongued until
+ mnMinNumberOfFrames are rendered.
+ */
+ sal_uInt32 mnMinNumberOfFrames;
+
+ /** Number of repeats for the simple duration
+
+ This specified the number of repeats. The
+ mnMinDuration times maRepeats yields the total
+ duration of this activity. If this value is
+ unspecified, the activity will repeat
+ indefinitely.
+ */
+ ::boost::optional<double> const maRepeats;
+
+ /// Fraction of simple time to accelerate animation
+ double mnAcceleration;
+
+ /// Fraction of simple time to decelerate animation
+ double mnDeceleration;
+
+ /// Shape, to get bounds from
+ ShapeSharedPtr mpShape;
+
+ /// LayerManager, to get page size from
+ ::basegfx::B2DVector maSlideBounds;
+
+ /// When true, activity is played reversed after mnDuration.
+ bool mbAutoReverse;
+ };
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a double value.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const NumberAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate >& xNode );
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a double value.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const EnumAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate >& xNode );
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a color value.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const ColorAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate >& xNode );
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a color value.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const HSLColorAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimateColor >& xNode );
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a pair of double values.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const PairAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate >& xNode );
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a string.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const StringAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate >& xNode );
+
+ /** Create an activity from an XAnimate node.
+
+ This method creates an animated activity from the
+ given XAnimate node, extracting all necessary
+ animation parameters from that. Note that due to the
+ animator parameter, the animation values must be
+ convertible to a bool value.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param xNode
+ The SMIL animation node to animate
+ */
+ static AnimationActivitySharedPtr createAnimateActivity(
+ const CommonParameters& rParms,
+ const BoolAnimationSharedPtr& rAnimator,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimate >& xNode );
+
+ /** Create a simple activity for the given animator
+
+ This method is suited to create activities for custom
+ animations, which need a simple double value and lasts
+ a given timespan. This activity always generates values
+ from the [0,1] range.
+
+ @param rParms
+ Factory parameter structure
+
+ @param rAnimator
+ Animator sub-object
+
+ @param bDirectionForward
+ If true, the activity goes 'forward', i.e. from 0 to
+ 1. With false, the direction is reversed.
+ */
+ static AnimationActivitySharedPtr createSimpleActivity(
+ const CommonParameters& rParms,
+ const NumberAnimationSharedPtr& rAnimator,
+ bool bDirectionForward );
+
+private:
+ // default: constructor/destructor disabed
+ ActivitiesFactory();
+ ~ActivitiesFactory();
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_ACTIVITIESFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/activitiesqueue.hxx b/slideshow/source/inc/activitiesqueue.hxx
new file mode 100644
index 000000000000..fe434e5c2db7
--- /dev/null
+++ b/slideshow/source/inc/activitiesqueue.hxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ACTIVITIESQUEUE_HXX
+#define INCLUDED_SLIDESHOW_ACTIVITIESQUEUE_HXX
+
+#include <deque>
+
+#include "activity.hxx"
+#include "unoviewcontainer.hxx"
+
+#include <canvas/elapsedtime.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp> // for boost::noncopyable
+
+
+/* Definition of ActivitiesQueue class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class handles the XSprite updates needed for
+ animations, such as moves, scales etc. You can add
+ activity objects to this class, which are called in a
+ round-robin fashion.
+ */
+ class ActivitiesQueue : private ::boost::noncopyable
+ {
+ public:
+ /** Create an ActivitiesQueue.
+
+ @param pPresTimer
+ Pointer to global presentation timer. Used for
+ adjusting and holding global presentation time.
+ */
+ ActivitiesQueue(
+ const ::boost::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer );
+ ~ActivitiesQueue();
+
+ /** Add the given activity to the queue.
+ */
+ bool addActivity( const ActivitySharedPtr& pActivity );
+
+ /** Process the activities queue.
+
+ This method performs the smallest atomic processing
+ possible on the queue (typically, this means one
+ activity get processed).
+ */
+ void process();
+
+ /** Call all dequeued activities' dequeued() method
+ */
+ void processDequeued();
+
+ /** Query state of the queue
+
+ @return false, if queue is empty, true otherwise
+ */
+ bool isEmpty() const;
+
+ /** Remove all pending activities from the queue.
+ */
+ void clear();
+
+ /** Gets the queue's timer object.
+ */
+ ::boost::shared_ptr< ::canvas::tools::ElapsedTime > const &
+ getTimer() const { return mpTimer; }
+
+ /** returns number of all activities, waiting, reinserted and dequeued
+ */
+ std::size_t size() const
+ {
+ return maCurrentActivitiesWaiting.size() + maCurrentActivitiesReinsert.size() + maDequeuedActivities.size();
+ }
+
+ private:
+ ::boost::shared_ptr< ::canvas::tools::ElapsedTime > mpTimer;
+
+ typedef ::std::deque< ActivitySharedPtr > ActivityQueue;
+
+ ActivityQueue maCurrentActivitiesWaiting; // currently running
+ // activities, that still
+ // await processing for this
+ // round
+
+ ActivityQueue maCurrentActivitiesReinsert; // currently running
+ // activities, that are
+ // already processed for
+ // this round, and wants
+ // to be reinserted next
+ // round
+
+ ActivityQueue maDequeuedActivities; // This list collects all activities which did not request
+ // a reinsertion. After the screen update has been
+ // performed, those are notified via dequeued(). This
+ // facilitates cleanup actions taking place _after_ the
+ // current frame has been displayed.
+ };
+
+ }
+}
+#endif /* INCLUDED_SLIDESHOW_ACTIVITIESQUEUE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/activity.hxx b/slideshow/source/inc/activity.hxx
new file mode 100644
index 000000000000..07df027a46f5
--- /dev/null
+++ b/slideshow/source/inc/activity.hxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ACTIVITY_HXX
+#define INCLUDED_SLIDESHOW_ACTIVITY_HXX
+
+#include <sal/types.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include "disposable.hxx"
+
+
+/* Definition of Activity interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ class Activity : public Disposable
+ {
+ public:
+ /** Perform the activity associated with this interface's
+ implementation.
+
+ @return true, if activity continues, or false, if activity has
+ ended.
+ */
+ virtual bool perform() = 0;
+
+ /** Calculates whether the activity lags time.
+
+ If this method returns a time lag greater than 0.0,
+ the ActivitiesQueue will adjust the global slideshow
+ time, by subtracting the given amount of lag.
+
+ @return time lag or 0.0. Value must be greater or
+ equal than zero.
+ */
+ virtual double calcTimeLag() const = 0;
+
+ /** Query whether this activity is still continuing
+
+ @return true, if this activity still
+ continues. Returns false, if activity has ended. It is
+ required that operator() returns false, when
+ isActive() returns false. Furthermore, it is required
+ that the inactive state is persistent; an activity
+ that has become inactive (i.e. isActive() once
+ returned false) must stay in that state eternally.
+ */
+ virtual bool isActive() const = 0;
+
+ /** Notifies the Activity that it has now left the
+ ActivitiesQueue
+
+ Use this method to react on the queue removal
+ event. For animated shapes, this is e.g. used to
+ switch back to the non-sprite presentation mode of the
+ shape.
+ */
+ virtual void dequeued() = 0;
+
+ /** Forces this activity deactivate and get to its end state
+ (if possible), but does _not_ dispose.
+ */
+ virtual void end() = 0;
+ };
+
+ typedef ::boost::shared_ptr< Activity > ActivitySharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ACTIVITY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animatableshape.hxx b/slideshow/source/inc/animatableshape.hxx
new file mode 100644
index 000000000000..1c84d289a523
--- /dev/null
+++ b/slideshow/source/inc/animatableshape.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATABLESHAPE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATABLESHAPE_HXX
+
+#include <boost/shared_ptr.hpp>
+
+#include "shape.hxx"
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Represents an animatable shape.
+
+ This interface adds animation handling methods to a
+ shape. It allows transparent switching between
+ sprite-based viewing and static painting, depending on
+ whether animations are currently running.
+ */
+ class AnimatableShape : public Shape
+ {
+ public:
+ // Animation methods
+ //------------------------------------------------------------------
+
+ /** Notify the Shape that an animation starts now
+
+ This method enters animation mode on all registered
+ views.
+
+ @attention This method is supposed to be called only
+ from the LayerManager, since it might involve shifting
+ shapes between different layers (and removing this
+ shape from the background layer in the first place)
+ */
+ virtual void enterAnimationMode() = 0;
+
+ /** Notify the Shape that it is no longer animated
+
+ This methods requests the Shape to end animation mode
+ on all registered views, if called more or equal the
+ times enterAnimationMode() was called. That is, the
+ Shape only leaves animation mode, if all requested
+ enterAnimationMode() call sites have issued their
+ matching leaveAnimationMode().
+
+ @attention This method is supposed to be called only
+ from the LayerManager, since it might involve shifting
+ shapes between different layers (and adding this
+ shape to the background layer again)
+ */
+ virtual void leaveAnimationMode() = 0;
+
+ };
+
+ typedef ::boost::shared_ptr< AnimatableShape > AnimatableShapeSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATABLESHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animatedsprite.hxx b/slideshow/source/inc/animatedsprite.hxx
new file mode 100644
index 000000000000..aae92dd5c125
--- /dev/null
+++ b/slideshow/source/inc/animatedsprite.hxx
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATEDSPRITE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATEDSPRITE_HXX
+
+#include <cppcanvas/customsprite.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include "viewlayer.hxx"
+
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+
+/* Definition of AnimatedSprite class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class provides the sprite for animated shapes.
+
+ Besides encapsulating the Canvas sprite for animated
+ shapes, this class also handles dynamic sprite resizing
+ and all the gory details of offset calculations and
+ rounding prevention.
+ */
+ class AnimatedSprite : private boost::noncopyable
+ {
+ public:
+ /** Create a new AnimatedSprite, for the given metafile
+ shape.
+
+ @param rViewLayer
+ The destination view layer, on which the animation should appear
+
+ @param rSpriteSizePixel
+ The overall size of the sprite in device coordinate
+ space, sufficient to display all transformations,
+ shape changes and clips.
+
+ @param nSpritePrio
+ Priority of the sprite. Must remain static over the
+ lifetime of this object
+ */
+ AnimatedSprite( const ViewLayerSharedPtr& rViewLayer,
+ const ::basegfx::B2DSize& rSpriteSizePixel,
+ double nSpritePrio );
+
+ /** Resize the sprite.
+
+ @param rSpriteSizePixel
+ The new size in pixel
+
+ @return true, if the resize was successful. If false
+ is returned, the sprite might be invalid.
+ */
+ bool resize( const ::basegfx::B2DSize& rSpriteSizePixel );
+
+ /** Set an offset for the content output in pixel
+
+ This method offsets the output on the sprite content
+ canvas by the specified amount of device pixel (for
+ subsequent render operations).
+ */
+ void setPixelOffset( const ::basegfx::B2DSize& rPixelOffset );
+
+ /// Retrieve current pixel offset for content output.
+ ::basegfx::B2DSize getPixelOffset() const;
+
+ /// Show the sprite
+ void show();
+
+ /// Hide the sprite
+ void hide();
+
+ /** Query the content canvas for the current sprite.
+
+ Note that this method must be called
+ <em>everytime</em> something is rendered to the
+ sprite, because XCustomSprite does not guarantee the
+ validity of the canvas after a render operation.
+
+ Furthermore, the view transformation on the returned
+ canvas is already correctly setup, matching the
+ associated destination canvas.
+ */
+ ::cppcanvas::CanvasSharedPtr getContentCanvas() const;
+
+ /** Move the sprite in device pixel space.
+
+ If the sprite is not yet created, this method has no
+ effect.
+ */
+ void movePixel( const ::basegfx::B2DPoint& rNewPos );
+
+ /** Set the alpha value of the sprite.
+
+ If the sprite is not yet created, this method has no
+ effect.
+ */
+ void setAlpha( double rAlpha );
+
+ /** Set a sprite clip in user coordinate space.
+
+ If the sprite is not yet created, this method has no
+ effect.
+ */
+ void clip( const ::basegfx::B2DPolyPolygon& rClip );
+
+ /** Clears a sprite clip
+
+ If the sprite is not yet created, this method has no
+ effect.
+ */
+ void clip();
+
+ /** Set a sprite transformation.
+
+ If the sprite is not yet created, this method has no
+ effect.
+ */
+ void transform( const ::basegfx::B2DHomMatrix& rTransform );
+
+ /** Set the sprite priority.
+
+ The sprite priority determines the ordering of the
+ sprites on screen, i.e. which sprite lies before which.
+
+ @param rPrio
+ The new sprite prio. Must be in the range [0,1]
+ */
+ void setPriority( double rPrio );
+
+ private:
+ ViewLayerSharedPtr mpViewLayer;
+
+ ::cppcanvas::CustomSpriteSharedPtr mpSprite;
+ ::basegfx::B2DSize maEffectiveSpriteSizePixel;
+ ::basegfx::B2DSize maContentPixelOffset;
+
+ double mnSpritePrio;
+ double mnAlpha;
+ ::boost::optional< ::basegfx::B2DPoint > maPosPixel;
+ ::boost::optional< ::basegfx::B2DPolyPolygon > maClip;
+ ::boost::optional< ::basegfx::B2DHomMatrix > maTransform;
+
+ bool mbSpriteVisible;
+ };
+
+ typedef ::boost::shared_ptr< AnimatedSprite > AnimatedSpriteSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATEDSPRITE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animation.hxx b/slideshow/source/inc/animation.hxx
new file mode 100644
index 000000000000..fe5e20112f00
--- /dev/null
+++ b/slideshow/source/inc/animation.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATION_HXX
+#define INCLUDED_SLIDESHOW_ANIMATION_HXX
+
+#include <animatableshape.hxx>
+#include <shapeattributelayer.hxx>
+
+
+/* Definition of Animation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a generic animation.
+
+ This interface is used by objects implementing the
+ Activity interface to drive the animation effect. Objects
+ implementing this interface will receive time-varying
+ animation values, which they can forward to the
+ appropriate attributes. The type of these animation values
+ is given in derived interfaces.
+
+ @see NumberAnimation
+ @see ColorAnimation
+ @see PairAnimation
+ */
+ class Animation
+ {
+ public:
+ virtual ~Animation() {}
+
+ /** Notify that the animation going active soon.
+
+ Implementers should preload any buffers, and create
+ any expensive objects at this time.
+
+ @param rShape
+ Shape to apply this animation to.
+
+ @param rAttrLayer
+ Attribute layer to play the animation on.
+ */
+ virtual void prefetch( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer ) = 0;
+
+ /** Notify that the animation is about to begin.
+
+ Implementers are free to start accompanying effects,
+ such as sounds, and the animation timer now.
+
+ @param rShape
+ Shape to apply this animation to.
+
+ @param rAttrLayer
+ Attribute layer to play the animation on.
+ */
+ virtual void start( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer ) = 0;
+
+ /** Notify that the animation is about to end.
+ */
+ virtual void end() = 0;
+ };
+
+ typedef ::boost::shared_ptr< Animation > AnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animationactivity.hxx b/slideshow/source/inc/animationactivity.hxx
new file mode 100644
index 000000000000..f364e29f54e3
--- /dev/null
+++ b/slideshow/source/inc/animationactivity.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONACTIVITY_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONACTIVITY_HXX
+
+#include "activity.hxx"
+#include "animatableshape.hxx"
+#include "shapeattributelayer.hxx"
+
+
+/* Definition of AnimationActivity interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Extends the Activity interface with animation-specific functions
+ */
+ class AnimationActivity : public Activity
+ {
+ public:
+ /** Sets targets (shape and attributeLayer)
+
+ Since attribute layers can only be generated when the
+ animation starts, the Activity owner must be able to
+ pass it into the Activity after initial creation. The
+ same applies to the actual shape the animation must
+ run for, since e.g. subsetted shapes are generated
+ close before the animation starts, too (this is not
+ necessary in and out of itself, but for performance
+ reasons. Otherwise, character iterations produce tons
+ of subset shapes).
+
+ @param rShape
+ Shape to play the animation on.
+
+ @param rAttrLayer
+ Attribute layer to change the animated values on.
+ */
+ virtual void setTargets( const AnimatableShapeSharedPtr& rShape,
+ const ShapeAttributeLayerSharedPtr& rAttrLayer ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< AnimationActivity > AnimationActivitySharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONACTIVITY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animationeventhandler.hxx b/slideshow/source/inc/animationeventhandler.hxx
new file mode 100644
index 000000000000..af11d0800863
--- /dev/null
+++ b/slideshow/source/inc/animationeventhandler.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONEVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONEVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+#include "animationnode.hxx"
+
+
+/* Definition of AnimationEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling animation events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle animation state change events.
+ */
+ class AnimationEventHandler
+ {
+ public:
+ virtual ~AnimationEventHandler() {}
+
+ /** Handle the event.
+
+ @param rNode
+ Animation node which caused this event to fire
+
+ @return true, if this handler has successfully
+ processed the animation event. When this method
+ returns false, possibly other, less prioritized
+ handlers are called, too.
+ */
+ virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< AnimationEventHandler > AnimationEventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONEVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animationfactory.hxx b/slideshow/source/inc/animationfactory.hxx
new file mode 100644
index 000000000000..16bdb33823f0
--- /dev/null
+++ b/slideshow/source/inc/animationfactory.hxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONFACTORY_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONFACTORY_HXX
+
+
+#include "numberanimation.hxx"
+#include "enumanimation.hxx"
+#include "coloranimation.hxx"
+#include "stringanimation.hxx"
+#include "boolanimation.hxx"
+#include "pairanimation.hxx"
+
+#include "shape.hxx"
+#include "shapeattributelayer.hxx"
+#include "shapemanager.hxx"
+
+#include <boost/noncopyable.hpp>
+
+
+namespace rtl
+{
+ class OUString;
+}
+
+
+/* Definition of AnimationFactory class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Factory for Animation objects
+
+ Given a SMIL XAnimate node, this factory generates the
+ appropriate Animation object from that, which will modify
+ the attribute as specified.
+ */
+ class AnimationFactory : private boost::noncopyable
+ {
+ public:
+ /** Classifies the attribute name.
+
+ This enum maps names to appropriate factory methods.
+ */
+ enum AttributeClass
+ {
+ /// Unknown, prolly invalid name
+ CLASS_UNKNOWN_PROPERTY,
+ /// Use createNumberPropertyAnimation
+ CLASS_NUMBER_PROPERTY,
+ /// Use createEnumPropertyAnimation
+ CLASS_ENUM_PROPERTY,
+ /// Use createColorPropertyAnimation
+ CLASS_COLOR_PROPERTY,
+ /// Use createStringPropertyAnimation
+ CLASS_STRING_PROPERTY,
+ /// Use createBoolPropertyAnimation
+ CLASS_BOOL_PROPERTY
+ };
+
+ static AttributeClass classifyAttributeName( const ::rtl::OUString& rAttrName );
+
+ /// Collection of flags common to all factory methods
+ enum FactoryFlags
+ {
+ /** Don't call enter/leaveAnimation for the Shape.
+
+ This is useful for set effects
+ */
+ FLAG_NO_SPRITE = 1
+ };
+
+ static NumberAnimationSharedPtr createNumberPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags=0 );
+
+ static EnumAnimationSharedPtr createEnumPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags=0 );
+
+ static ColorAnimationSharedPtr createColorPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags=0 );
+
+ /** Create scale or move animation
+
+ @param nTransformType
+ Must be one of
+ animations::AnimationTransformType::TRANSLATE or
+ animations::AnimationTransformType::SCALE.
+ */
+ static PairAnimationSharedPtr createPairPropertyAnimation( const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ sal_Int16 nTransformType,
+ int nFlags=0 );
+
+ static StringAnimationSharedPtr createStringPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags=0 );
+
+ static BoolAnimationSharedPtr createBoolPropertyAnimation( const ::rtl::OUString& rAttrName,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags=0 );
+
+ static NumberAnimationSharedPtr createPathMotionAnimation( const ::rtl::OUString& rSVGDPath,
+ sal_Int16 nAdditive,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ int nFlags=0);
+ private:
+ // default: constructor/destructor disabed
+ AnimationFactory();
+ ~AnimationFactory();
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animationfunction.hxx b/slideshow/source/inc/animationfunction.hxx
new file mode 100644
index 000000000000..2e94bc193a30
--- /dev/null
+++ b/slideshow/source/inc/animationfunction.hxx
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONFUNCTION_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONFUNCTION_HXX
+
+#include <sal/config.h>
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of AnimationFunction interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface describing an abstract animation function.
+
+ Use this interface to model time-dependent animation
+ functions of one variable.
+ */
+ class AnimationFunction
+ {
+ public:
+ virtual ~AnimationFunction() {}
+
+ /** Operator to calculate function value.
+
+ This method calculates the function value for the
+ given time instant t.
+
+ @param t
+ Current time instant, must be in the range [0,1]
+
+ @return the function value, typically in relative
+ user coordinate space ([0,1] range).
+ */
+ virtual double operator()( double t ) const = 0;
+
+ };
+
+ typedef ::boost::shared_ptr< AnimationFunction > AnimationFunctionSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONFUNCTION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animationnode.hxx b/slideshow/source/inc/animationnode.hxx
new file mode 100644
index 000000000000..3f341fcb5695
--- /dev/null
+++ b/slideshow/source/inc/animationnode.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONNODE_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONNODE_HXX
+
+#include "disposable.hxx"
+
+#include <com/sun/star/animations/XAnimationNode.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace slideshow {
+namespace internal {
+
+/** This interface is used to mirror every XAnimateNode object
+ in the presentation core.
+*/
+class AnimationNode : public Disposable
+{
+public:
+ /** The current state of this AnimationNode
+ */
+ enum NodeState {
+ /// Invalid state, node is disposed or otherwise invalid
+ INVALID =0,
+ /// Unresolved start time
+ UNRESOLVED =1,
+ /// Resolved start time, node will start eventually
+ RESOLVED =2,
+ /// Node is active
+ ACTIVE =4,
+ /// Node is frozen (no longer active, but changes remain in place)
+ FROZEN =8,
+ /// Node has completed an active lifecycle,
+ /// and any effect is removed from the document
+ ENDED =16
+ };
+
+ /** Query the corresponding XAnimationNode.
+ */
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >
+ getXAnimationNode() const = 0;
+
+ /** Init this node
+
+ If this node is not in state INVALID, init() sets up the
+ node state and schedules necessary events.
+ If this node has children, they have their init() called, too.
+ You will call this method whenever a slide is going to be
+ shown.
+
+ @return true, if init was successful; state has changed to UNRESOLVED
+ */
+ virtual bool init() = 0;
+
+ /** Resolve node start time
+
+ Nodes can have unresolved start times, i.e. indefinite
+ start time for container nodes, or child nodes whose
+ parent has not yet started. Calling this method fixes
+ the node's start time. This does not mean that this
+ node immediately starts its animations, that is only
+ the case for begin=0.0. The node will change its state
+ to RESOLVED.
+
+ @return true, if a start event was successfully scheduled.
+ */
+ virtual bool resolve() = 0;
+
+ /** Immediately start this node
+
+ This method starts the animation on this node, without
+ begin timeout. The node will change its state to ACTIVE.
+
+ @return true, if start was successful. This method
+ might return false, if e.g. a restart is not permitted
+ on this node.
+ */
+ virtual bool activate() = 0;
+
+ /** Immediately stop this node
+
+ This method stops the animation on this node. The node
+ will change its state to either ENDED or FROZEN,
+ depending on XAnimationNode attributes.
+ */
+ virtual void deactivate() = 0;
+
+ /** End the animation on this node
+
+ This method force-ends animation on this node. Parents
+ may call this for their children, if their active
+ duration ends. An ended animation will no longer have
+ any effect on the shape attributes. The node will
+ change its state to ENDED.
+ */
+ virtual void end() = 0;
+
+ /** Query node state
+
+ @return the current state of this animation node.
+ */
+ virtual NodeState getState() const = 0;
+
+ /** Register a deactivating listener
+
+ This method registers another AnimationNode as an
+ deactivating listener, which gets notified via a
+ notifyDeactivating() call. The node calls all
+ registered listener, when it leaves the ACTIVE state.
+
+ @param rNotifee AnimationNode to notify
+ */
+ virtual bool registerDeactivatingListener(
+ const ::boost::shared_ptr< AnimationNode >& rNotifee ) = 0;
+
+ /** Called to notify another AnimationNode's deactivation
+
+ @param rNotifier The instance who calls this method.
+ */
+ virtual void notifyDeactivating(
+ const ::boost::shared_ptr< AnimationNode >& rNotifier ) = 0;
+
+ /** Query node whether it has an animation pending.
+
+ @return true, if this node (or at least one of its children)
+ has an animation pending. Used to determine if the main
+ sequence is actually empty, or contains effects
+ */
+ virtual bool hasPendingAnimation() const = 0;
+};
+
+typedef ::boost::shared_ptr< AnimationNode > AnimationNodeSharedPtr;
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/animationnodefactory.hxx b/slideshow/source/inc/animationnodefactory.hxx
new file mode 100644
index 000000000000..bc0c64314d2d
--- /dev/null
+++ b/slideshow/source/inc/animationnodefactory.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ANIMATIONNODEFACTORY_HXX
+#define INCLUDED_SLIDESHOW_ANIMATIONNODEFACTORY_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/animations/XAnimationNode.hpp>
+
+#include "subsettableshapemanager.hxx"
+#include "animationnode.hxx"
+#include "slideshowcontext.hxx"
+#include "eventqueue.hxx"
+#include "activitiesqueue.hxx"
+#include "usereventqueue.hxx"
+
+#include <boost/noncopyable.hpp>
+#include <vector>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /* Definition of AnimationNodeFactory class */
+
+ class AnimationNodeFactory : private boost::noncopyable
+ {
+ public:
+ /** Create an AnimatioNode for the given XAnimationNode
+ */
+ static AnimationNodeSharedPtr createAnimationNode( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xNode,
+ const ::basegfx::B2DVector& rSlideSize,
+ const SlideShowContext& rContext );
+
+
+#if defined(VERBOSE) && defined(DBG_UTIL)
+ static void showTree( AnimationNodeSharedPtr& pRootNode );
+# define SHOW_NODE_TREE(a) AnimationNodeFactory::showTree(a)
+#else
+# define SHOW_NODE_TREE(a)
+#endif
+
+ private:
+ // default: constructor/destructor disabled
+ AnimationNodeFactory();
+ ~AnimationNodeFactory();
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ANIMATIONNODEFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/attributableshape.hxx b/slideshow/source/inc/attributableshape.hxx
new file mode 100644
index 000000000000..1efba90b7205
--- /dev/null
+++ b/slideshow/source/inc/attributableshape.hxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ATTRIBUTABLESHAPE_HXX
+#define INCLUDED_SLIDESHOW_ATTRIBUTABLESHAPE_HXX
+
+#include <boost/shared_ptr.hpp>
+
+#include "animatableshape.hxx"
+#include "shapeattributelayer.hxx"
+#include "doctreenodesupplier.hxx"
+
+namespace slideshow
+{
+ namespace internal
+ {
+ // forward declaration necessary, because methods use AttributableShapeSharedPtr
+ class AttributableShape;
+
+ typedef ::boost::shared_ptr< AttributableShape > AttributableShapeSharedPtr;
+
+ /** Represents an animatable shape, that can have its
+ attributes changed.
+
+ Over an animatable shape, this interface adds attribute
+ modification methods. Furthermore, the shape can be
+ queried for sub items, which in turn can be separated out
+ into own AttributableShapes.
+ */
+ class AttributableShape : public AnimatableShape
+ {
+ public:
+ // Attribute layer methods
+ //------------------------------------------------------------------
+
+ /** Create a new shape attribute layer.
+
+ This method creates a new layer for shape attributes,
+ which lies atop of all previous attribute layers. That
+ is most typically used when a new SMIL animation
+ starts (which according to the spec always lies atop
+ of all previous animations). Thus, subsequent calls to
+ this method generate a sandwich of attribute layers,
+ which in total define the shape's attributes.
+
+ Please note that the attribute layers do <em>not</em>
+ contain the underlying XShape's attributes as
+ default. Instead, attributes not explicitely set by
+ animations remain in invalid state, allowing the
+ shape's paint method to determine whether they have to
+ override the underlying graphical shape
+ representation. XShape attributes must be passed
+ explicitely to animations which need them (e.g. 'by'
+ animations).
+
+ @return the new layer
+ */
+ virtual ShapeAttributeLayerSharedPtr createAttributeLayer() = 0;
+
+ /** Revoke a previously generated attribute layer.
+
+ This method revokes a previously generated attribute
+ layer, and removes the effect of that layer from this
+ shape. The layer need not be the current toplevel
+ layer, it can also be revoked from in between.
+
+ @param rLayer
+ Layer to revoke. Must have been generated by
+ createAttributeLayer() at the same Shape.
+
+ @return true, if layer was successfully removed, false
+ otherwise (e.g. if the given layer was not generated
+ for this shape).
+ */
+ virtual bool revokeAttributeLayer( const ShapeAttributeLayerSharedPtr& rLayer ) = 0;
+
+ /** Get the topmost shape attribute layer (if any).
+
+ This method returns the topmost layer for shape
+ attributes, i.e. the one which ultimately determines
+ the shape's look.
+
+ Please note that the attribute layers do <em>not</em>
+ contain the underlying XShape's attributes as
+ default. Instead, attributes not explicitely set by
+ animations remain in invalid state, allowing the
+ shape's paint method to determine whether they have to
+ override the underlying graphical shape
+ representation. XShape attributes must be passed
+ explicitely to animations which need them (e.g. 'by'
+ animations).
+
+ @return the topmost layer
+ */
+ virtual ShapeAttributeLayerSharedPtr getTopmostAttributeLayer() const = 0;
+
+
+ /** Change default shape visibility
+
+ This method hides or unhides a shape. Note that every
+ attribute layer generated for this shape is able to
+ override the setting given here, until it is revoked.
+
+ @param bVisible
+ When true, shape will be visible, when false,
+ invisible (modulo attribute layer overrides).
+ */
+ virtual void setVisibility( bool bVisible ) = 0;
+
+ // Sub-item handling
+ //------------------------------------------------------------------
+
+ /** Retrieve interface for DocTreeNode creation.
+
+ This method provides the caller with a reference to
+ the DocTreeNodeSupplier interface, which can be used
+ to request specific tree nodes for this shape.
+ */
+ virtual const DocTreeNodeSupplier& getTreeNodeSupplier() const = 0;
+ virtual DocTreeNodeSupplier& getTreeNodeSupplier() = 0;
+
+ /** Query the subset this shape displays.
+
+ This method returns a tree node denoting the subset
+ displayed by this shape. If this shape is not a subset
+ shape, an empty tree node should be returned. If this
+ shape is a subset, and itself has subsetted children,
+ this method might return more than the shape is
+ actually displaying (because a single DocTreeNode is
+ not able to model holes in the range).
+ */
+ virtual DocTreeNode getSubsetNode() const = 0;
+
+ /** Query a subset Shape, if already existent at this
+ object
+
+ This method returns a clone of this Shape, which
+ renders only the selected subset of itself, but only
+ if such a subset has been explicitely created before.
+
+ @param rTreeNode
+ A DocTreeNode instance queried from this Shape, which
+ specifies the subset of the Shape to render.
+
+ @return a NULL Shape pointer, if no subset exists for
+ the given DocTreeNode.
+ */
+ virtual AttributableShapeSharedPtr getSubset( const DocTreeNode& rTreeNode ) const = 0;
+
+ /** Create a subset Shape
+
+ This method creates a clone of this Shape, which
+ renders only the selected subset of itself. Multiple
+ createSubset() calls for the same DocTreeNode will all
+ share the same subset shape.
+
+ The original shape (i.e. the one this method is called
+ on) will cease to display the selected subset
+ part. That is, together the shapes will display the
+ original content, but the content of all subset shapes
+ and their original shape will always be mutually
+ disjunct.
+
+ After deregistering the subset shape a matching number
+ of times via revokeSubset(), the original shape will
+ resume displaying the subsetted part.
+
+ @attention To maintain view integrity, this method
+ should only be called from the LayerManager
+
+ @param o_rSubset
+ The requested Shape
+
+ @param rTreeNode
+ A DocTreeNode instance queried from this Shape, which
+ specifies the subset of the Shape to render
+
+ @return true, if the shape was newly created, and
+ false, if an already existing subset is returned.
+ */
+ virtual bool createSubset( AttributableShapeSharedPtr& o_rSubset,
+ const DocTreeNode& rTreeNode ) = 0;
+
+ /** Revoke a previously generated shape subset.
+
+ After revoking a subset shape, the corresponding
+ subset part will become visible again on the original
+ shape.
+
+ @attention To maintain view integrity, this method
+ should only be called from the LayerManager
+
+ @param rShape
+ The subset to revoke
+
+ @return true, if the last client called
+ revokeSubset().
+ */
+ virtual bool revokeSubset( const AttributableShapeSharedPtr& rShape ) = 0;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ATTRIBUTABLESHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/attributemap.hxx b/slideshow/source/inc/attributemap.hxx
new file mode 100644
index 000000000000..24db268a352b
--- /dev/null
+++ b/slideshow/source/inc/attributemap.hxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ATTRIBUTEMAP_HXX
+#define INCLUDED_SLIDESHOW_ATTRIBUTEMAP_HXX
+
+#include <rtl/ustring.hxx>
+
+/* Definition of AttributeMap helper function */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Type of to-be-animated attribute.
+
+ This enum describes the type of an animated
+ attribute.
+ */
+ enum AttributeType
+ {
+ ATTRIBUTE_INVALID,
+ ATTRIBUTE_CHAR_COLOR,
+ ATTRIBUTE_CHAR_FONT_NAME,
+ ATTRIBUTE_CHAR_HEIGHT,
+ ATTRIBUTE_CHAR_POSTURE,
+ ATTRIBUTE_CHAR_ROTATION,
+ ATTRIBUTE_CHAR_UNDERLINE,
+ ATTRIBUTE_CHAR_WEIGHT,
+ ATTRIBUTE_COLOR,
+ ATTRIBUTE_DIMCOLOR,
+ ATTRIBUTE_FILL_COLOR,
+ ATTRIBUTE_FILL_STYLE,
+ ATTRIBUTE_HEIGHT,
+ ATTRIBUTE_LINE_COLOR,
+ ATTRIBUTE_LINE_STYLE,
+ ATTRIBUTE_OPACITY,
+ ATTRIBUTE_ROTATE,
+ ATTRIBUTE_SKEW_X,
+ ATTRIBUTE_SKEW_Y,
+ ATTRIBUTE_VISIBILITY,
+ ATTRIBUTE_WIDTH,
+ ATTRIBUTE_POS_X,
+ ATTRIBUTE_POS_Y
+ };
+
+ /** Map attribute name to AttributeType enum
+
+ @returns ATTRIBUTE_INVALID, if name was not found in the
+ mapping table.
+ */
+ AttributeType mapAttributeName( const ::rtl::OUString& rAttrName );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ATTRIBUTEMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/boolanimation.hxx b/slideshow/source/inc/boolanimation.hxx
new file mode 100644
index 000000000000..c7d951ee14fa
--- /dev/null
+++ b/slideshow/source/inc/boolanimation.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_BOOLANIMATION_HXX
+#define INCLUDED_SLIDESHOW_BOOLANIMATION_HXX
+
+#include "animation.hxx"
+
+
+/* Definition of BoolAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a bool animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes that have
+ only two discrete values (on and off, or true and false,
+ for example).
+ */
+ class BoolAnimation : public Animation
+ {
+ public:
+ typedef bool ValueType;
+
+ /** Set the animation to the given value
+
+ @param bValue
+ Current animation value.
+ */
+ virtual bool operator()( ValueType bValue ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< BoolAnimation > BoolAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_BOOLANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/coloranimation.hxx b/slideshow/source/inc/coloranimation.hxx
new file mode 100644
index 000000000000..d7c149dc2ee0
--- /dev/null
+++ b/slideshow/source/inc/coloranimation.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_COLORANIMATION_HXX
+#define INCLUDED_SLIDESHOW_COLORANIMATION_HXX
+
+#include "animation.hxx"
+#include "rgbcolor.hxx"
+
+
+/* Definition of ColorAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a color animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes representable
+ by a color value.
+ */
+ class ColorAnimation : public Animation
+ {
+ public:
+ typedef RGBColor ValueType;
+
+ /** Set the animation to the given color value
+
+ @param rColor
+ Current animation value.
+ */
+ virtual bool operator()( const ValueType& rColor ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ColorAnimation > ColorAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_COLORANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/cursormanager.hxx b/slideshow/source/inc/cursormanager.hxx
new file mode 100644
index 000000000000..4b06e963f201
--- /dev/null
+++ b/slideshow/source/inc/cursormanager.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_CURSORMANAGER_HXX
+#define INCLUDED_SLIDESHOW_CURSORMANAGER_HXX
+
+#include <sal/types.h>
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of CursorManager interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling the view cursor.
+
+ Classes implementing this interface interact with the
+ View, arbitrating access to the mouse cursor shape.
+ */
+ class CursorManager
+ {
+ public:
+ virtual ~CursorManager() {}
+
+ /** Request different cursor shape.
+
+ @param nCursorShape
+ Shape ID of the new mouse cursor
+ */
+ virtual bool requestCursor( sal_Int16 nCursorShape ) = 0;
+
+ /** Reset cursor to default one.
+
+ This method resets the cursor to whatever default to
+ manager deems appropriate.
+ */
+ virtual void resetCursor() = 0;
+ };
+
+ typedef ::boost::shared_ptr< CursorManager > CursorManagerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_CURSORMANAGER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/debug.hxx b/slideshow/source/inc/debug.hxx
new file mode 100644
index 000000000000..4bf7d43a4696
--- /dev/null
+++ b/slideshow/source/inc/debug.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DEBUG_HXX
+#define INCLUDED_SLIDESHOW_DEBUG_HXX
+
+#include <osl/diagnose.h>
+
+#if OSL_DEBUG_LEVEL > 1
+
+#include "animationnode.hxx"
+
+
+namespace slideshow { namespace internal {
+
+void Debug_ShowNodeTree (const AnimationNodeSharedPtr& rpNode);
+
+// Change this to a valid filename. The file is created anew with every
+// office start (and execution of at least one TRACE... command.)
+#define TRACE_LOG_FILE_NAME "d:\\tmp\\log.txt"
+
+class DebugTraceScope
+{
+public:
+ DebugTraceScope (const sal_Char* sFormat, ...);
+ ~DebugTraceScope (void);
+private:
+ static const sal_Int32 mnBufferSize = 512;
+ sal_Char* msMessage;
+};
+
+void SAL_CALL DebugTraceBegin (const sal_Char* sFormat, ...);
+void SAL_CALL DebugTraceEnd (const sal_Char* sFormat, ...);
+void SAL_CALL DebugTraceMessage (const sal_Char* sFormat, ...);
+
+} } // end of namespace ::slideshow::internal
+
+
+#define TRACE_BEGIN DebugTraceBegin
+#define TRACE_END DebugTraceEnd
+#define TRACE DebugTraceMessage
+#define TRACE_SCOPE DebugTraceScope aTraceScope
+
+#else // OSL_DEBUG_LEVEL > 1
+
+#define TRACE_BEGIN 1 ? ((void)0) : DebugTraceBegin
+#define TRACE_END 1 ? ((void)0) : DebugTraceEnd
+#define TRACE 1 ? ((void)0) : DebugTraceMessage
+#define TRACE_SCOPE
+
+#endif // OSL_DEBUG_LEVEL > 1
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/delayevent.hxx b/slideshow/source/inc/delayevent.hxx
new file mode 100644
index 000000000000..c4db6e66b178
--- /dev/null
+++ b/slideshow/source/inc/delayevent.hxx
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_DELAYEVENT_HXX
+#define INCLUDED_SLIDESHOW_DELAYEVENT_HXX
+
+#include <boost/function.hpp>
+
+#include "event.hxx"
+#include "debug.hxx"
+#include <boost/noncopyable.hpp>
+
+namespace slideshow {
+namespace internal {
+
+/** Event, which delays the functor call the given amount of time
+ */
+class Delay : public Event, private ::boost::noncopyable
+{
+public:
+ typedef ::boost::function0<void> FunctorT;
+
+ template <typename FuncT>
+ Delay( FuncT const& func,
+ double nTimeout
+#if OSL_DEBUG_LEVEL > 1
+ , const ::rtl::OUString& rsDescription
+ ) : Event(rsDescription),
+#else
+ ) :
+#endif
+ mnTimeout(nTimeout), maFunc(func), mbWasFired(false) {}
+
+ Delay( const boost::function0<void>& func,
+ double nTimeout
+#if OSL_DEBUG_LEVEL > 1
+ , const ::rtl::OUString& rsDescription
+ ) : Event(rsDescription),
+#else
+ ) :
+#endif
+ mnTimeout(nTimeout),
+ maFunc(func),
+ mbWasFired(false) {}
+
+ // Event:
+ virtual bool fire();
+ virtual bool isCharged() const;
+ virtual double getActivationTime( double nCurrentTime ) const;
+ // Disposable:
+ virtual void dispose();
+
+private:
+ double const mnTimeout;
+ FunctorT maFunc;
+ bool mbWasFired;
+};
+
+#if OSL_DEBUG_LEVEL <= 1
+
+/** Generate delay event
+
+ @param func
+ Functor to call when the event fires.
+
+ @param nTimeout
+ Timeout in seconds, to wait until functor is called.
+
+ @return generated delay event
+*/
+template <typename FuncT>
+inline EventSharedPtr makeDelay_( FuncT const& func, double nTimeout )
+{
+ return EventSharedPtr( new Delay( func, nTimeout ) );
+}
+
+/** Generate immediate event
+
+ @param func
+ Functor to call when the event fires.
+
+ @return generated immediate event.
+*/
+template <typename FuncT>
+inline EventSharedPtr makeEvent_( FuncT const& func )
+{
+ return EventSharedPtr( new Delay( func, 0.0 ) );
+}
+
+
+// Strip away description.
+#define makeDelay(f, t, d) makeDelay_(f, t)
+#define makeEvent(f, d) makeEvent_(f)
+
+#else // OSL_DEBUG_LEVEL > 1
+
+class Delay_ : public Delay {
+public:
+ template <typename FuncT>
+ Delay_( FuncT const& func, double nTimeout,
+ char const* from_function, char const* from_file, int from_line,
+ const ::rtl::OUString& rsDescription)
+ : Delay(func, nTimeout, rsDescription),
+ FROM_FUNCTION(from_function),
+ FROM_FILE(from_file), FROM_LINE(from_line) {}
+
+ char const* const FROM_FUNCTION;
+ char const* const FROM_FILE;
+ int const FROM_LINE;
+};
+
+template <typename FuncT>
+inline EventSharedPtr makeDelay_(
+ FuncT const& func, double nTimeout,
+ char const* from_function, char const* from_file, int from_line,
+ const ::rtl::OUString& rsDescription)
+{
+ return EventSharedPtr( new Delay_( func, nTimeout,
+ from_function, from_file, from_line, rsDescription) );
+}
+
+#define makeDelay(f, t, d) makeDelay_(f, t, \
+ BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, \
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(d)))
+#define makeEvent(f, d) makeDelay_(f, 0.0, \
+ BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, \
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(d)))
+
+#endif // OSL_DEBUG_LEVEL <= 1
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_DELAYEVENT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/disposable.hxx b/slideshow/source/inc/disposable.hxx
new file mode 100644
index 000000000000..5e3c4f4d765e
--- /dev/null
+++ b/slideshow/source/inc/disposable.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DISPOSABLE_HXX
+#define INCLUDED_SLIDESHOW_DISPOSABLE_HXX
+
+#include <sal/types.h>
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of Disposable interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Disposable interface
+
+ With ref-counted objects, deleting object networks
+ containing cycles requires a dispose() call, to enforce
+ every object to call dispose on and release local
+ references.
+ */
+ class Disposable
+ {
+ public:
+ virtual ~Disposable() {}
+
+ /** Dispose all object references.
+
+ An implementor of this method must first call
+ dispose() on any of its external references, and
+ release them after that.
+ */
+ virtual void dispose() = 0;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_DISPOSABLE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/doctreenode.hxx b/slideshow/source/inc/doctreenode.hxx
new file mode 100644
index 000000000000..c8ad37f9f109
--- /dev/null
+++ b/slideshow/source/inc/doctreenode.hxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DOCTREENODE_HXX
+#define INCLUDED_SLIDESHOW_DOCTREENODE_HXX
+
+#include <sal/types.h>
+#include <vector>
+
+
+/* Definition of DocTreeNode class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** This class represents kind of a DOM tree node for shape
+ text
+
+ In order to animate subsets of shape text, we need
+ information about the logical and formatting structure of
+ that text (lines, paragraphs, words etc.). This is
+ represented in a tree structure, with DocTreeNodes as the
+ nodes. Instances of this class can be queried from the
+ DocTreeNodeSupplier interface.
+
+ This class has nothing to do with the Draw document tree.
+ */
+ class DocTreeNode
+ {
+ public:
+ /// Type of shape entity represented by this node
+ enum NodeType
+ {
+ NODETYPE_INVALID=0,
+
+ /// This node represents a full shape
+ NODETYPE_FORMATTING_SHAPE=1,
+ /// This node represents a line
+ NODETYPE_FORMATTING_LINE=2,
+
+ /// This node represents a full shape
+ NODETYPE_LOGICAL_SHAPE=128,
+ /// This node represents a paragraph
+ NODETYPE_LOGICAL_PARAGRAPH=129,
+ /// This node represents a sentence
+ NODETYPE_LOGICAL_SENTENCE=130,
+ /// This node represents a word
+ NODETYPE_LOGICAL_WORD=131,
+ /// This node represents a character
+ NODETYPE_LOGICAL_CHARACTER_CELL=132
+ };
+
+ // classificators for above text entity types
+ static bool isLogicalNodeType( NodeType eType ) { return eType > 127; }
+ static bool isFormattingNodeType( NodeType eType ) { return eType > 0 && eType < 128; }
+
+ /** Create empty tree node
+ */
+ DocTreeNode() :
+ mnStartIndex(-1),
+ mnEndIndex(-1),
+ meType(NODETYPE_INVALID)
+ {
+ }
+
+ /** Create tree node from start and end index.
+
+ Create a tree node for the given range and type.
+
+ @param nStartIndex
+ Start index
+
+ @param nEndIndex
+ End index (exclusive)
+
+ @param eType
+ Node type
+ */
+ DocTreeNode( sal_Int32 nStartIndex,
+ sal_Int32 nEndIndex,
+ NodeType eType ) :
+ mnStartIndex(nStartIndex),
+ mnEndIndex(nEndIndex),
+ meType(eType)
+ {
+ }
+
+ bool isEmpty() const { return mnStartIndex == mnEndIndex; }
+
+ sal_Int32 getStartIndex() const { return mnStartIndex; }
+ sal_Int32 getEndIndex() const { return mnEndIndex; }
+ void setStartIndex( sal_Int32 nIndex ) { mnStartIndex = nIndex; }
+ void setEndIndex( sal_Int32 nIndex ) { mnEndIndex = nIndex; }
+
+ NodeType getType() const { return meType; }
+
+ void reset()
+ {
+ mnStartIndex = -1;
+ mnEndIndex = -1;
+ meType = NODETYPE_INVALID;
+ }
+
+ private:
+ sal_Int32 mnStartIndex;
+ sal_Int32 mnEndIndex;
+ NodeType meType;
+
+ };
+
+ typedef ::std::vector< DocTreeNode > VectorOfDocTreeNodes;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_DOCTREENODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/doctreenodesupplier.hxx b/slideshow/source/inc/doctreenodesupplier.hxx
new file mode 100644
index 000000000000..0dd0125502ef
--- /dev/null
+++ b/slideshow/source/inc/doctreenodesupplier.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_DOCTREENODESUPPLIER_HXX
+#define INCLUDED_SLIDESHOW_DOCTREENODESUPPLIER_HXX
+
+#include "doctreenode.hxx"
+
+
+/* Definition of DocTreeNodeSupplier interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface to retrieve DocTreeNodes from subsettable
+ shapes.
+
+ Shapes which implement the AttributableShape interface
+ also provides this interface, providing methods to
+ retrieve specific DocTreeNode objects from the shape. The
+ methods mainly distinguish various ways on how to specify
+ the actual DocTreeNode to return.
+
+ If a requested DocTreeNode is not available when one of
+ the methods below is called, an empty DocTreeNode will be
+ returned (the predicate DocTreeNode::isEmpty() will return
+ true). If, on the other hand, the shape cannot determine,
+ for internal reasons, the internal tree node structure,
+ all those methods will throw an
+ ShapeLoadFailedException. This is, in fact, a delayed error
+ that could also have been reported during shape
+ construction, but might be postponed until the missing
+ information is actually requested.
+ */
+ class DocTreeNodeSupplier
+ {
+ public:
+ /** Query number of tree nodes of the given type this
+ shape contains.
+
+ The value returned by this method minus one is the
+ maximum value permissible at the getTreeNode()
+ method, for the given node type.
+
+ @throws ShapeLoadFailedException, if tree node structure
+ cannot be determined.
+ */
+ virtual sal_Int32 getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const = 0; // throw ShapeLoadFailedException;
+
+ /** Create DocTreeNode from shape.
+
+ This method creates a DocTreeNode from a shape, a
+ given node type and a running index into the shape's
+ DocTreeNodes of the given type.
+
+ @param nNodeIndex
+ Starting with 0, every DocTreeNode of the shape that
+ has type eNodeType is indexed. The DocTreeNode whose
+ index equals nNodeIndex will be returned.
+
+ @param eNodeType
+ Type of the node to return
+
+ @return the DocTreeNode found, or the empty
+ DocTreeNode, if nothing was found.
+
+ @throws ShapeLoadFailedException, if tree node structure
+ cannot be determined.
+ */
+ virtual DocTreeNode getTreeNode( sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const = 0; // throw ShapeLoadFailedException;
+
+ /** Query number of tree nodes of the given type this
+ subset contains.
+
+ The value returned by this method minus one is the
+ maximum value permissible at the
+ getSubsetTreeNode() method, for the given node
+ type.
+
+ @param rParentNode
+ The parent node, below which the number of tree nodes
+ of the given type shall be counted.
+
+ @param eNodeType
+ Node type to count.
+
+ @throws ShapeLoadFailedException, if tree node structure
+ cannot be determined.
+ */
+ virtual sal_Int32 getNumberOfSubsetTreeNodes( const DocTreeNode& rParentNode,
+ DocTreeNode::NodeType eNodeType ) const = 0; // throw ShapeLoadFailedException;
+
+ /** Create DocTreeNode from shape subset.
+
+ This method creates a DocTreeNode from a shape, a
+ parent tree node, a given node type and a running
+ index into the shape's DocTreeNodes of the given type.
+
+ @param rParentNode
+ Parent node, below which the tree node with the given
+ type shall be selected.
+
+ @param nNodeIndex
+ Starting with 0, every DocTreeNode of the shape that
+ has type eNodeType is indexed. The DocTreeNode whose
+ index equals nNodeIndex will be returned.
+
+ @param eNodeType
+ Type of the node to return
+
+ @return the DocTreeNode found, or the empty
+ DocTreeNode, if nothing was found.
+
+ @throws ShapeLoadFailedException, if tree node structure
+ cannot be determined.
+ */
+ virtual DocTreeNode getSubsetTreeNode( const DocTreeNode& rParentNode,
+ sal_Int32 nNodeIndex,
+ DocTreeNode::NodeType eNodeType ) const = 0; // throw ShapeLoadFailedException;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_DOCTREENODESUPPLIER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/enumanimation.hxx b/slideshow/source/inc/enumanimation.hxx
new file mode 100644
index 000000000000..56dda31685ec
--- /dev/null
+++ b/slideshow/source/inc/enumanimation.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_ENUMANIMATION_HXX
+#define INCLUDED_SLIDESHOW_ENUMANIMATION_HXX
+
+#include "animation.hxx"
+
+
+/* Definition of EnumAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining an enum animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes representable
+ by a set of constant values, such as UNO constantsm, or enums.
+ */
+ class EnumAnimation : public Animation
+ {
+ public:
+ typedef sal_Int16 ValueType;
+
+ /** Set the animation to value k
+
+ @param k
+ Current animation value (must be in an
+ attribute-specific permissible range). Overflowing
+ values will be clipped to the permissible range
+ internally.
+ */
+ virtual bool operator()( ValueType k ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< EnumAnimation > EnumAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_ENUMANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/event.hxx b/slideshow/source/inc/event.hxx
new file mode 100644
index 000000000000..2c0c338b2ff1
--- /dev/null
+++ b/slideshow/source/inc/event.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_EVENT_HXX
+#define INCLUDED_SLIDESHOW_EVENT_HXX
+
+#include "disposable.hxx"
+#include "debug.hxx"
+#include <rtl/ustring.hxx>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+namespace slideshow {
+namespace internal {
+
+/** Definition of Event interface
+ */
+class Event : public Disposable
+{
+public:
+#if OSL_DEBUG_LEVEL > 1
+ Event (const ::rtl::OUString& rsDescription) : msDescription(rsDescription) {};
+#endif
+
+ /** Execute the event.
+
+ @return true, if event was successfully executed.
+ */
+ virtual bool fire() = 0;
+
+ /** Query whether this event is still charged, i.e. able
+ to fire.
+
+ Inactive events are ignored by the normal event
+ containers (EventQueue, UserEventQueue etc.), and no
+ explicit fire() is called upon them.
+
+ @return true, if this event has already been fired.
+ */
+ virtual bool isCharged() const = 0;
+
+ /** Query the activation time instant this event shall be
+ fired, if it was inserted at instant nCurrentTime into
+ the queue.
+
+ @param nCurrentTime
+ The time from which the activation time is to be
+ calculated from.
+
+ @return the time instant in seconds, on which this
+ event is to be fired.
+ */
+ virtual double getActivationTime( double nCurrentTime ) const = 0;
+
+#if OSL_DEBUG_LEVEL > 1
+ ::rtl::OUString GetDescription (void) const { return msDescription; }
+
+private:
+ const ::rtl::OUString msDescription;
+#endif
+};
+
+typedef ::boost::shared_ptr< Event > EventSharedPtr;
+typedef ::std::vector< EventSharedPtr > VectorOfEvents;
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_EVENT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/eventhandler.hxx b/slideshow/source/inc/eventhandler.hxx
new file mode 100644
index 000000000000..87a30a943443
--- /dev/null
+++ b/slideshow/source/inc/eventhandler.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_EVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of EventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for event handling objects.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle events.
+ */
+ class EventHandler
+ {
+ public:
+ virtual ~EventHandler() {}
+
+ /** Handle the event.
+
+ @return true, if this handler has successfully
+ processed the event. When this method returns false,
+ possibly other, less prioritized handlers are called,
+ too.
+ */
+ virtual bool handleEvent() = 0;
+ };
+
+ typedef ::boost::shared_ptr< EventHandler > EventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_EVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/eventmultiplexer.hxx b/slideshow/source/inc/eventmultiplexer.hxx
new file mode 100644
index 000000000000..23b550adb8e7
--- /dev/null
+++ b/slideshow/source/inc/eventmultiplexer.hxx
@@ -0,0 +1,663 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_EVENTMULTIPLEXER_HXX
+#define INCLUDED_SLIDESHOW_EVENTMULTIPLEXER_HXX
+
+#include "eventhandler.hxx"
+#include "hyperlinkhandler.hxx"
+#include "mouseeventhandler.hxx"
+#include "animationeventhandler.hxx"
+#include "pauseeventhandler.hxx"
+#include "shapelistenereventhandler.hxx"
+#include "shapecursoreventhandler.hxx"
+#include "userpainteventhandler.hxx"
+#include "vieweventhandler.hxx"
+#include "viewrepainthandler.hxx"
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+
+namespace slideshow {
+namespace internal {
+
+class EventQueue;
+class UnoViewContainer;
+class AnimationNode;
+
+struct EventMultiplexerImpl;
+
+/** This class multiplexes user-activated and
+ slide-show global events.
+
+ This class listens at the XSlideShowView and fires events
+ registered for certain user actions. Furthermore, global
+ slide show state changes (such as start or end of a slide)
+ are handled as well. Note that registered events which
+ have a non-zero timeout (i.e. events that return non-zero
+ from getActivationTime()) will not be fired immediately
+ after the user action occured, but only after the given
+ timeout. Which is actually a feature.
+*/
+class EventMultiplexer : private ::boost::noncopyable
+{
+public:
+ /** Create an event multiplexer
+
+ @param rEventQueue
+ Reference to the main event queue. Since we hold this
+ object by plain reference, it must live longer than we
+ do. On the other hand, that queue must not fire events
+ after this object is destroyed, since we might
+ schedule events there which itself contain plain
+ references to this object. Basically, EventQueue and
+ EventMultiplexer should have the same lifetime, and since
+ this is not possible, both must be destructed in a
+ phased mode: first clear both of any remaining events,
+ then destruct them.
+
+ @param rViewContainer
+ Globally managed list of all registered views. Used to
+ determine event sources, and for registering view listeners
+ at.
+ */
+ EventMultiplexer( EventQueue& rEventQueue,
+ UnoViewContainer const& rViewContainer );
+ ~EventMultiplexer();
+
+
+ // Management methods
+ // =========================================================
+
+ /** Clear all registered handlers.
+ */
+ void clear();
+
+
+ // Automatic mode methods
+ // =========================================================
+
+ /** Change automatic mode.
+
+ @param bIsAuto
+ When true, events will be fired automatically, not
+ only triggered by UI events. When false, auto events
+ will quit.
+ */
+ void setAutomaticMode( bool bIsAuto );
+
+ /** Get automatic mode setting.
+ */
+ bool getAutomaticMode() const;
+
+ /** Set the timeout for automatic mode.
+
+ @param nTimeout
+ Timeout, between end of effect until start of next
+ effect.
+ */
+ void setAutomaticTimeout( double nTimeout );
+
+ /** Get automatic mode timeout value.
+ */
+ double getAutomaticTimeout() const;
+
+ // Handler registration methods
+ // =========================================================
+
+ /** Register an event handler that will be called when views are
+ changed.
+
+ For each view added, viewAdded() will be called on the
+ handler. For each view removed, viewRemoved() will be
+ called. Each modified view will cause a viewChanged() call on
+ each handler.
+
+ You don't need to deregister the handler, it will be
+ automatically removed, once the pointee becomes stale.
+
+ @param rHandler
+ Handler to call.
+ */
+ void addViewHandler( const ViewEventHandlerWeakPtr& rHandler );
+ void removeViewHandler( const ViewEventHandlerWeakPtr& rHandler );
+
+ /** Register an event handler that will be called when a view gets
+ clobbered.
+
+ Note that <em>all</em> registered handlers will be called when
+ the event. This is in contrast to the mouse events below.
+
+ @param rHandler
+ Handler to call when a view needs a repaint
+ */
+ void addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler );
+ void removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when
+ XShapeListeners are changed.
+
+ @param rHandler
+ Handler to call when a shape listener changes
+ */
+ void addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler );
+ void removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when
+ XShapeListeners are changed.
+
+ @param rHandler
+ Handler to call when a shape listener changes
+ */
+ void addShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler );
+ void removeShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when
+ user paint parameters change.
+
+ @param rHandler
+ Handler to call when a shape listener changes
+ */
+ void addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler );
+ void removeUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when the
+ user requests the next effect.
+
+ For every nextEffect event, only one of the handlers
+ registered here is called. The handlers are considered
+ with decreasing priority, i.e. the handler with the
+ currently highest priority will be called.
+
+ @param rHandler
+ Handler to call when the next effect should start
+
+ @param nPriority
+ Priority with which the handlers are called. The
+ higher the priority, the earlier this handler will be
+ tried.
+ */
+ void addNextEffectHandler( const EventHandlerSharedPtr& rHandler,
+ double nPriority );
+ void removeNextEffectHandler( const EventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when the
+ slide is just shown.
+
+ Note that <em>all</em> registered handlers will be called
+ when the slide start occurs. This is in contrast to
+ the mouse events below.
+
+ @param rHandler
+ Handler to call when the next slide starts
+ */
+ void addSlideStartHandler( const EventHandlerSharedPtr& rHandler );
+ void removeSlideStartHandler( const EventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when the
+ slide is about to vanish.
+
+ Note that <em>all</em> registered handlers will be
+ called when the slide end occurs. This is in contrast
+ to the mouse events below.
+
+ @param rHandler
+ Handler to call when the current slide ends
+ */
+ void addSlideEndHandler( const EventHandlerSharedPtr& rHandler );
+ void removeSlideEndHandler( const EventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when an
+ XAnimationNode starts its active duration.
+
+ Note that <em>all</em> registered handlers will be called
+ when the animation start occurs. This is in contrast to
+ the mouse events below.
+
+ @param rHandler
+ Handler to call when the animation start
+ */
+ void addAnimationStartHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+ void removeAnimationStartHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when an
+ XAnimationNode ends its active duration.
+
+ Note that <em>all</em> registered handlers will be called
+ when the animation end occurs. This is in contrast to
+ the mouse events below.
+
+ @param rHandler
+ Handler to call when the animation ends
+ */
+ void addAnimationEndHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+ void removeAnimationEndHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when the
+ main animation sequence of a slide ends its active
+ duration.
+
+ Note that <em>all</em> registered handlers will be
+ called when the animation end occurs. This is in
+ contrast to the mouse events below.
+
+ @param rHandler
+ Handler to call when the animation ends
+ */
+ void addSlideAnimationsEndHandler(
+ const EventHandlerSharedPtr& rHandler );
+ void removeSlideAnimationsEndHandler(
+ const EventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when an
+ XAudio node's sound stops playing.
+
+ Note that <em>all</em> registered handlers will be
+ called when the audio stops. This is in contrast to
+ the mouse events below.
+
+ @param rHandler
+ Handler to call when the audio stops
+ */
+ void addAudioStoppedHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+ void removeAudioStoppedHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+
+ /** Register an event handler that will be called when an
+ XCommand node's with the command STOPAUDIO is activated.
+
+ Note that <em>all</em> registered handlers will be
+ called when the audio stops. This is in contrast to
+ the mouse events below.
+
+ @param rHandler
+ Handler to call when command is activated
+ */
+ void addCommandStopAudioHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+ void removeCommandStopAudioHandler(
+ const AnimationEventHandlerSharedPtr& rHandler );
+
+ /** Register a handler that is called when the show enters
+ or exits pause mode.
+ */
+ void addPauseHandler( const PauseEventHandlerSharedPtr& rHandler );
+ void removePauseHandler( const PauseEventHandlerSharedPtr& rHandler );
+
+ /** Register a mouse handler that is called on mouse click
+
+ For every mouse click, only one of the handlers
+ registered here is called. The handlers are considered
+ with decreasing priority, i.e. the handler with the
+ currently highest priority will be called.
+
+ Since the handlers can reject down and up events
+ individually, handlers should expect to be called with
+ non-matching down and up-press counts. If your handler
+ cannot cope with that, it must have the highest
+ priority of all added handlers.
+ */
+ void addClickHandler( const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority );
+ void removeClickHandler( const MouseEventHandlerSharedPtr& rHandler );
+
+ /** Register a mouse handler that is called on a double
+ mouse click
+
+ For every mouse double click, only one of the handlers
+ registered here is called. The handlers are considered
+ with decreasing priority, i.e. the handler with the
+ currently highest priority will be called.
+
+ Since the handlers can reject down and up events
+ individually, handlers should expect to be called with
+ non-matching down and up-press counts. If your handler
+ cannot cope with that, it must have the highest
+ priority of all added handlers.
+ */
+ void addDoubleClickHandler( const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority );
+ void removeDoubleClickHandler( const MouseEventHandlerSharedPtr& rHandler );
+
+ /** Register a mouse handler that is called for mouse moves.
+
+ For every mouse move, only one of the handlers
+ registered here is called. The handlers are considered
+ with decreasing priority, i.e. the handler with the
+ currently highest priority will be called.
+ */
+ void addMouseMoveHandler( const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority );
+ void removeMouseMoveHandler( const MouseEventHandlerSharedPtr& rHandler );
+
+
+ /** Registers a hyperlink click handler.
+
+ For every hyperlink click, only one of the handlers registered
+ here is called. The handlers are considered with decreasing
+ priority, i.e. the handler with the currently highest priority
+ will be called.
+
+ @param rHandler
+ @param nPriority
+ */
+ void addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler,
+ double nPriority );
+ void removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler );
+
+
+ // External event notifications
+ // =========================================================
+
+ /** View added.
+
+ This method adds another view, which the show is
+ displayed on. On every added view, the EventMultiplexer
+ registers mouse and motion event listeners.
+ */
+ bool notifyViewAdded( const UnoViewSharedPtr& rView );
+
+ /** View removed
+
+ This method removes a view. Registered mouse and
+ motion event listeners are revoked.
+ */
+ bool notifyViewRemoved( const UnoViewSharedPtr& rView );
+
+ /** View changed
+
+ This method announces a changed view to all view
+ listeners. View changes include size and transformation.
+
+ @param rView
+ View that has changed
+ */
+ bool notifyViewChanged( const UnoViewSharedPtr& rView );
+
+ /** View changed
+
+ This method announces a changed view to all view
+ listeners. View changes include size and transformation.
+
+ @param xView
+ View that has changed
+ */
+ bool notifyViewChanged( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XSlideShowView>& xView );
+
+ /** All Views changed
+
+ This method announces to all view listeners that
+ <em>every</em> known view has changed. View changes include
+ size and transformation.
+ */
+ bool notifyViewsChanged();
+
+ /** View clobbered
+
+ This method announces that the given view has been clobbered
+ by something external to the slideshow, and needs an update.
+
+ @param xView
+ View that has been clobbered
+ */
+ bool notifyViewClobbered( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XSlideShowView>& xView );
+
+ /** New shape event listener added
+
+ This method announces that the given listener was added for
+ the specified shape.
+
+ @return true, if at least one handler successfully processed
+ the notification.
+ */
+ bool notifyShapeListenerAdded( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XShapeEventListener>& xListener,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape );
+
+ /** A shape event listener was removed
+
+ This method announces that the given listener was removed for
+ the specified shape.
+
+ @return true, if at least one handler successfully processed
+ the notification.
+ */
+ bool notifyShapeListenerRemoved( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XShapeEventListener>& xListener,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape );
+
+ /** A new shape cursor was set
+
+ This method announces that the given cursor was set for the
+ specified shape.
+
+ @return true, if at least one handler successfully processed
+ the notification.
+ */
+ bool notifyShapeCursorChange( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape,
+ sal_Int16 nPointerShape );
+
+ /** Notify a new user paint color
+
+ Sending this notification also implies that user paint is
+ enabled. User paint denotes the feature to draw colored lines
+ on top of the slide content.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyUserPaintColor( RGBColor const& rUserColor );
+
+ /** Notify a new user paint width
+
+ Sending this notification also implies that user paint is
+ enabled. .
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyUserPaintStrokeWidth( double rUserStrokeWidth );
+
+
+ /** Notify a new user paint erase all ink mode
+
+ Sending this notification also implies that user paint is
+ enabled. User paint denotes the feature to draw colored lines
+ on top of the slide content.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyEraseAllInk( bool const& rEraseAllInk );
+ bool notifySwitchPenMode();
+ bool notifySwitchEraserMode();
+ bool notifyEraseInkWidth( sal_Int32 rEraseInkSize );
+
+ /** Notify that user paint is disabled
+
+ User paint denotes the feature to draw colored lines on top of
+ the slide content.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyUserPaintDisabled();
+
+ /** Notify that the user requested the next effect.
+
+ This requests the slideshow to display the next
+ effect, or move to the next slide, if none are left.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyNextEffect();
+
+ /** Notify that a new slide is about to be displayed
+ */
+ bool notifySlideTransitionStarted();
+
+ /** Notify that a new slide has started
+
+ This method is to be used from the Presentation object
+ to signal that a new slide is starting now. This will
+ invoke all registered slide start handlers.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifySlideStartEvent();
+
+ /** Notify that a slide has ended
+
+ This method is to be used from the Presentation object
+ to signal that a slide is ending now. This will invoke
+ all registered slide end handlers.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifySlideEndEvent();
+
+ /** Notify that the given node enters its active duration.
+
+ This method is to be used from the AnimationNode
+ objects to signal that the active duration
+ begins. This will invoke all registered animation
+ start handlers.
+
+ @param rNode
+ Node which enters active duration.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyAnimationStart( const boost::shared_ptr<AnimationNode>& rNode );
+
+ /** Notify that the given node leaves its active duration.
+
+ This method is to be used from the AnimationNode
+ objects to signal that the active duration
+ ends now. This will invoke all registered animation
+ end handlers.
+
+ @param rNode
+ Node which leaves active duration.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyAnimationEnd( const boost::shared_ptr<AnimationNode>& rNode );
+
+ /** Notify that the slide animations sequence leaves its
+ active duration.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifySlideAnimationsEnd();
+
+ /** Notify that for the given node, audio output has stopped.
+
+ This method is to be used from the AnimationNode
+ objects to signal that audio playback has just
+ stopped. This will invoke all registered audio
+ stopped andlers.
+
+ @param rNode
+ Node for which audio has stopped.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyAudioStopped( const boost::shared_ptr<AnimationNode>& rNode );
+
+ /** Notify that the show has entered or exited pause mode
+
+ This method is to be used from the Presentation object
+ to signal that a slide is entering (bPauseShow=true)
+ or exiting (bPauseShow=false) pause mode. This will
+ invoke all registered slide end handlers.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyPauseMode( bool bPauseShow );
+
+ /** Notify that all audio has to be stoped.
+
+ This method is used by XCommand nodes and all sound
+ playing nodes should listen for this command and
+ stop theire sounds when its fired.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyCommandStopAudio( const boost::shared_ptr<AnimationNode>& rNode );
+
+ /** Botifies that a hyperlink has been clicked.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ bool notifyHyperlinkClicked( ::rtl::OUString const& hyperLink );
+
+private:
+ boost::scoped_ptr<EventMultiplexerImpl> mpImpl;
+};
+
+} // namespace internal
+} // namespace Presentation
+
+#endif /* INCLUDED_SLIDESHOW_EVENTMULTIPLEXER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/eventqueue.hxx b/slideshow/source/inc/eventqueue.hxx
new file mode 100644
index 000000000000..19f3358f1298
--- /dev/null
+++ b/slideshow/source/inc/eventqueue.hxx
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EVENTQUEUE_HXX
+#define INCLUDED_SLIDESHOW_EVENTQUEUE_HXX
+
+#include <canvas/elapsedtime.hxx>
+#include <osl/mutex.hxx>
+
+#include "event.hxx"
+
+#include <boost/noncopyable.hpp>
+#include <functional>
+#include <queue>
+#include <vector>
+
+
+/* Definition of ActivitiesQueue class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** This class handles events in a presentation. Events are
+ time instants where e.g. effects start.
+ */
+ class EventQueue : private ::boost::noncopyable
+ {
+ public:
+ EventQueue(
+ ::boost::shared_ptr< ::canvas::tools::ElapsedTime >
+ const & pPresTimer );
+
+ ~EventQueue();
+
+ /** Add the given event to the queue. The event is fired
+ at, or shortly after, its Event::getActivationTime instant.
+ */
+ bool addEvent( const EventSharedPtr& event );
+
+ /** Add the given event to the queue. The event is fired
+ at, or shortly after, its Event::getActivationTime instant.
+ The difference to addEvent() is that events added during
+ process() are postponed to next process().
+ */
+ bool addEventForNextRound( const EventSharedPtr& event );
+
+ /** Another way to control the order of asynchronous event
+ exeqution. Use this method to schedule events that are to
+ be executed after all regular events that have no delay,
+ even when they schedule new regular events without delay.
+ */
+ bool addEventWhenQueueIsEmpty (const EventSharedPtr& rpEvent);
+
+ /** Process the event queue.
+
+ This method executes all events whose timeout has
+ expired when calling this method (i.e. all events
+ whose scheduled time is less or equal the current
+ time).
+
+ Check for the next available event's timeout via
+ nextTimeout(), or whether the queue is empty
+ altogether via isEmpty().
+ */
+ void process();
+
+ /** Query state of the queue
+
+ @return false, if queue is empty, true otherwise
+ */
+ bool isEmpty() const;
+
+ /** Query timeout for the topmost event in the queue.
+
+ @return Timeout in seconds, until the next event is
+ ready. The time returned here is relative to the pres
+ timer (i.e. the timer specified at the EventQueue
+ constructor). When the queue is empty (i.e. isEmpty()
+ returns true), the returned value is the highest
+ representable double value
+ (::std::numeric_limits<double>::max()). If the topmost
+ event in the queue is already pending, the timeout
+ returned here will actually be negative.
+ */
+ double nextTimeout() const;
+
+ /** Remove all pending events from the queue.
+ */
+ void clear();
+
+ /** Forces an empty queue, firing all events immediately
+ without minding any times.
+ @attention do only call from event loop, this calls process_()!
+ */
+ void forceEmpty();
+
+ /** Gets the queue's timer object.
+ */
+ ::boost::shared_ptr< ::canvas::tools::ElapsedTime > const &
+ getTimer() const { return mpTimer; }
+
+ private:
+ mutable ::osl::Mutex maMutex;
+
+ struct EventEntry : public ::std::unary_function<EventEntry, bool>
+ {
+ EventSharedPtr pEvent;
+ double nTime;
+
+ bool operator<( const EventEntry& ) const; // to leverage priority_queue's default compare
+
+ EventEntry( EventSharedPtr const& p, double t )
+ : pEvent(p), nTime(t) {}
+ };
+
+ typedef ::std::priority_queue< EventEntry > ImplQueueType;
+ ImplQueueType maEvents;
+ typedef ::std::vector<EventEntry> EventEntryVector;
+ EventEntryVector maNextEvents;
+ ImplQueueType maNextNextEvents;
+ void process_( bool bFireAllEvents );
+
+ // perform timing of events via relative time
+ // measurements. The world time starts, when the
+ // EventQueue object is created
+ ::boost::shared_ptr< ::canvas::tools::ElapsedTime > mpTimer;
+ };
+
+ }
+}
+#endif /* INCLUDED_SLIDESHOW_EVENTQUEUE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/expressionnode.hxx b/slideshow/source/inc/expressionnode.hxx
new file mode 100644
index 000000000000..47cb6abf0898
--- /dev/null
+++ b/slideshow/source/inc/expressionnode.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EXPRESSIONNODE_HXX
+#define INCLUDED_SLIDESHOW_EXPRESSIONNODE_HXX
+
+#include "animationfunction.hxx"
+
+
+/* Definition of ExpressionNode interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Refinement of AnimationFunction
+
+ This interface is used by the SMIL function parser, to
+ collapse constant values into precalculated, single nodes.
+ */
+ class ExpressionNode : public AnimationFunction
+ {
+ public:
+ /** Predicate whether this node is constant.
+
+ This predicate returns true, if this node is
+ neither time- nor ViewInfo dependent. This allows
+ for certain obtimizations, i.e. not the full
+ expression tree needs be represented by
+ ExpressionNodes.
+
+ @returns true, if this node is neither time- nor
+ ViewInfo dependent
+ */
+ virtual bool isConstant() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ExpressionNode > ExpressionNodeSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_EXPRESSIONNODE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/expressionnodefactory.hxx b/slideshow/source/inc/expressionnodefactory.hxx
new file mode 100644
index 000000000000..b0ea5e9a2205
--- /dev/null
+++ b/slideshow/source/inc/expressionnodefactory.hxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EXPRESSIONNODEFACTORY_HXX
+#define INCLUDED_SLIDESHOW_EXPRESSIONNODEFACTORY_HXX
+
+#include "expressionnode.hxx"
+
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+
+
+/* Definition of ExpressionNodeFactory class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** ExpressionNode factory
+
+ This class can be used to generate a wide variety of
+ ExpressionNode objects, e.g. when parsing SMIL function
+ expressions.
+ */
+ class ExpressionNodeFactory
+ {
+ public:
+ static ExpressionNodeSharedPtr createConstantValueExpression( double rConstantValue );
+
+ static ExpressionNodeSharedPtr createValueTExpression ();
+
+ static ExpressionNodeSharedPtr createPlusExpression ( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS );
+ static ExpressionNodeSharedPtr createMinusExpression ( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS );
+ static ExpressionNodeSharedPtr createMultipliesExpression( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS );
+ static ExpressionNodeSharedPtr createDividesExpression ( const ExpressionNodeSharedPtr& rLHS,
+ const ExpressionNodeSharedPtr& rRHS );
+
+ /** Composes two ExpressionNode function.
+
+ The resulting expression will calculate
+ rOuterFunction( rInnerFunction(t) ).
+ */
+ static ExpressionNodeSharedPtr createComposedExpression ( const ExpressionNodeSharedPtr& rOuterFunction,
+ const ExpressionNodeSharedPtr& rInnerFunction );
+
+ static ExpressionNodeSharedPtr createMinExpression ( const ExpressionNodeSharedPtr& rOuterFunction,
+ const ExpressionNodeSharedPtr& rInnerFunction );
+
+ static ExpressionNodeSharedPtr createMaxExpression ( const ExpressionNodeSharedPtr& rOuterFunction,
+ const ExpressionNodeSharedPtr& rInnerFunction );
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_EXPRESSIONNODEFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/externalmediashape.hxx b/slideshow/source/inc/externalmediashape.hxx
new file mode 100644
index 000000000000..fa1ccc3922ef
--- /dev/null
+++ b/slideshow/source/inc/externalmediashape.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_EXTERNALMEDIASHAPE_HXX
+#define INCLUDED_SLIDESHOW_EXTERNALMEDIASHAPE_HXX
+
+#include <boost/shared_ptr.hpp>
+
+#include "shape.hxx"
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Represents a shape containing media (video, sound).
+
+ This interface adds media handling methods to a shape. It
+ allows starting/stopping and pausing playback.
+ */
+ class ExternalMediaShape : public Shape
+ {
+ public:
+ // Animation methods
+ //------------------------------------------------------------------
+
+ /** Notify the Shape that it should start with playback
+
+ This method enters playback mode on all registered
+ views. It makes the media initially visible (for videos).
+ */
+ virtual void play() = 0;
+
+ /** Notify the Shape that it should stop playback
+
+ This method leaves playback mode on all registered
+ views. The media is then rewound to the start, and
+ removed from screen (for videos)
+ */
+ virtual void stop() = 0;
+
+ /** Notify the Shape that it should pause playback
+
+ This method stops playback on all registered
+ views. The media stays visible (for videos)
+ */
+ virtual void pause() = 0;
+
+ /** Query whether the media is currently playing.
+ */
+ virtual bool isPlaying() const = 0;
+
+ /** Set media time in seconds.
+
+ @param fTime
+ Time in seconds of the media time line, that should now be
+ presented
+ */
+ virtual void setMediaTime(double fTime) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ExternalMediaShape > ExternalMediaShapeSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_EXTERNALMEDIASHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/framerate.hxx b/slideshow/source/inc/framerate.hxx
new file mode 100644
index 000000000000..4ffe891b31fc
--- /dev/null
+++ b/slideshow/source/inc/framerate.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_FRAMERATE_HXX
+#define INCLUDED_SLIDESHOW_FRAMERATE_HXX
+
+#include <sal/types.h>
+
+namespace slideshow { namespace internal {
+
+/** Some frame rate related data.
+*/
+class FrameRate
+{
+public:
+ /** The minimum number of frames per second is used to calculate the
+ minimum number of frames that is to be shown for active activities.
+ */
+ static const sal_Int32 MinimumFramesPerSecond = 10;
+
+ /** Aim high with the number of preferred number of frames per second.
+ This number is the maximum as well and the true number will be lower.
+ */
+ static const sal_Int32 PreferredFramesPerSecond = 50;
+};
+
+} } // end of namespace slideshow::internal
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/hslcolor.hxx b/slideshow/source/inc/hslcolor.hxx
new file mode 100644
index 000000000000..a2bd8e918bd0
--- /dev/null
+++ b/slideshow/source/inc/hslcolor.hxx
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_HSLCOLOR_HXX
+#define INCLUDED_SLIDESHOW_HSLCOLOR_HXX
+
+#include <cppcanvas/color.hxx>
+
+
+/* Definition of HSLColor class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class RGBColor;
+
+ /** HSL color space class.
+ */
+ class HSLColor
+ {
+ public:
+ HSLColor();
+ explicit HSLColor( ::cppcanvas::Color::IntSRGBA nRGBColor );
+ HSLColor( double nHue, double nSaturation, double nLuminance );
+ explicit HSLColor( const RGBColor& rColor );
+
+ /** Hue of the color.
+
+ @return hue, is in the range [0,360]
+ */
+ double getHue() const;
+
+ /** Saturation of the color.
+
+ @return saturation, is in the range [0,1]
+ */
+ double getSaturation() const;
+
+ /** Luminance of the color.
+
+ @return luminance, is in the range [0,1]
+ */
+ double getLuminance() const;
+
+ /** Get the RGB red value.
+ */
+ double getRed() const;
+
+ /** Get the RGB green value.
+ */
+ double getGreen() const;
+
+ /** Get the RGB blue value.
+ */
+ double getBlue() const;
+
+ /** Create an RGB color object.
+ */
+ RGBColor getRGBColor() const;
+
+ struct HSLTriple
+ {
+ HSLTriple();
+ HSLTriple( double nHue, double nSaturation, double nLuminance );
+
+ double mnHue;
+ double mnSaturation;
+ double mnLuminance;
+ };
+
+ private:
+ // default copy/assignment are okay
+ // HSLColor(const HSLColor&);
+ // HSLColor& operator=( const HSLColor& );
+
+ HSLTriple maHSLTriple;
+
+ /// Pre-calculated value, needed for conversion back to RGB
+ double mnMagicValue;
+ };
+
+ HSLColor operator+( const HSLColor& rLHS, const HSLColor& rRHS );
+ HSLColor operator*( const HSLColor& rLHS, const HSLColor& rRHS );
+ HSLColor operator*( double nFactor, const HSLColor& rRHS );
+
+ /** HSL color linear interpolator.
+
+ @param t
+ As usual, t must be in the [0,1] range
+
+ @param bCCW
+ When true, hue interpolation happens counter-clockwise
+ */
+ HSLColor interpolate( const HSLColor& rFrom, const HSLColor& rTo, double t, bool bCCW=true );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_HSLCOLOR_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/hslcoloranimation.hxx b/slideshow/source/inc/hslcoloranimation.hxx
new file mode 100644
index 000000000000..b86e801eaeed
--- /dev/null
+++ b/slideshow/source/inc/hslcoloranimation.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_HSLCOLORANIMATION_HXX
+#define INCLUDED_SLIDESHOW_HSLCOLORANIMATION_HXX
+
+#include "animation.hxx"
+#include "hslcolor.hxx"
+
+
+/* Definition of HSLColorAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a HSL color animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes representable
+ by a HSL color value.
+ */
+ class HSLColorAnimation : public Animation
+ {
+ public:
+ typedef HSLColor ValueType;
+
+ /** Set the animation to the given color value
+
+ @param rColor
+ Current animation value.
+ */
+ virtual bool operator()( const ValueType& rColor ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< HSLColorAnimation > HSLColorAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_HSLCOLORANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/hyperlinkarea.hxx b/slideshow/source/inc/hyperlinkarea.hxx
new file mode 100644
index 000000000000..07be394a540e
--- /dev/null
+++ b/slideshow/source/inc/hyperlinkarea.hxx
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_HYPERLINKAREA_HXX
+#define INCLUDED_SLIDESHOW_HYPERLINKAREA_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <utility>
+
+namespace rtl {
+ class OUString;
+}
+namespace basegfx {
+ class B2DRange;
+}
+
+/* Definition of HyperlinkArea interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** HyperlinkArea interface
+
+ Implementers of this interface provide information for
+ hyperlink sensitive areas.
+ */
+ class HyperlinkArea
+ {
+ public:
+ typedef std::pair< ::basegfx::B2DRange,
+ ::rtl::OUString > HyperlinkRegion;
+
+ typedef std::vector<HyperlinkRegion> HyperlinkRegions;
+
+ /** Request hyperlink-sensitive areas.
+
+ @return a vector of hyperlink-sensitive areas, plus
+ the URI associated to them.
+ */
+ virtual HyperlinkRegions getHyperlinkRegions() const = 0;
+
+ /** Retrieve priority of link area
+
+ @return the priority of the link area. Link areas with
+ higher priority will receive hyperlink clicks in favor
+ of areas with less priority, if they cover the same
+ place on screen.
+ */
+ virtual double getHyperlinkPriority() const = 0;
+
+ /** Functor struct, for area ordering
+
+ This defines a strict weak ordering of areas, sort key
+ is the object ptr value. Most typical use is for
+ associative containers holding areas.
+ */
+ struct lessThanArea
+ {
+ // make functor adaptable (to boost::bind)
+ typedef bool result_type;
+
+ bool operator()(const boost::shared_ptr< HyperlinkArea >& rLHS,
+ const boost::shared_ptr< HyperlinkArea >& rRHS) const
+ {
+ const double nPrioL( rLHS->getHyperlinkPriority() );
+ const double nPrioR( rRHS->getHyperlinkPriority() );
+
+ // if prios are equal, tie-break on ptr value
+ return nPrioL == nPrioR ? rLHS.get() < rRHS.get() : nPrioL < nPrioR;
+ }
+ };
+ };
+
+ typedef boost::shared_ptr< HyperlinkArea > HyperlinkAreaSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_HYPERLINKAREA_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/hyperlinkhandler.hxx b/slideshow/source/inc/hyperlinkhandler.hxx
new file mode 100644
index 000000000000..25b0d5bc4843
--- /dev/null
+++ b/slideshow/source/inc/hyperlinkhandler.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_HYPERLINKHANDLER_HXX
+#define INCLUDED_SLIDESHOW_HYPERLINKHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of EventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling hyperlink clicks.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle hyperlink events.
+ */
+ class HyperlinkHandler
+ {
+ public:
+ /** Handle the event.
+
+ @param rLink
+ The actual hyperlink URI
+
+ @return true, if this handler has successfully
+ processed the event. When this method returns false,
+ possibly other, less prioritized handlers are called,
+ too.
+ */
+ virtual bool handleHyperlink( ::rtl::OUString const& rLink ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< HyperlinkHandler > HyperlinkHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_HYPERLINKHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/interruptabledelayevent.hxx b/slideshow/source/inc/interruptabledelayevent.hxx
new file mode 100644
index 000000000000..baa074ca8625
--- /dev/null
+++ b/slideshow/source/inc/interruptabledelayevent.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_INTERRUPTABLEDELAYEVENT_HXX
+#define INCLUDED_SLIDESHOW_INTERRUPTABLEDELAYEVENT_HXX
+
+#include "delayevent.hxx"
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Event, which delays calling passed Event's fire() method
+ the given amount of time.
+
+ This is actually a facade around the passed event object,
+ that passes on all calls to that object, and the sole
+ contribution of itself is the delay.
+ */
+ class DelayFacade : public Event
+ {
+ public:
+ DelayFacade( const EventSharedPtr& rEvent,
+ double nTimeout ) :
+#if OSL_DEBUG_LEVEL > 1
+ Event(::rtl::OUString::createFromAscii("DelayFacade")),
+#endif
+ mpEvent( rEvent ),
+ mnTimeout( nTimeout )
+ {
+ }
+
+ virtual bool fire()
+ {
+ if( mpEvent && isCharged() )
+ {
+ // pass on directly - we're supposed to be called
+ // from EventQueue here, anyway - and if not,
+ // we're only keeping that incorrect transitively.
+ return mpEvent->fire();
+ }
+
+ return false;
+ }
+
+ virtual bool isCharged() const
+ {
+ // pass on to wrappee - this ensures that we return
+ // false on isCharged(), even if the other event has
+ // been fired outside our own fire() method
+ return !mpEvent ? false : mpEvent->isCharged();
+ }
+
+ virtual double getActivationTime( double nCurrentTime ) const
+ {
+ // enforce _our_ timeout to our clients (this
+ // overrides any timeout possibly set at the wrappee!)
+ return nCurrentTime + mnTimeout;
+ }
+
+ virtual void dispose()
+ {
+ mpEvent.reset();
+ }
+
+ private:
+ EventSharedPtr mpEvent;
+ double mnTimeout;
+ };
+
+ /// Return value for makeInterruptableDelay()
+ struct InterruptableEventPair
+ {
+ /** This member contains a pointer to the timeout
+ event. When enqueued, this event will fire the
+ requested action only after the specified timeout.
+ */
+ EventSharedPtr mpTimeoutEvent;
+
+ /** This member contains a pointer to the interruption
+ event. When enqueued, this event will fire
+ immediately, interrupting a potentially waiting
+ timeout event.
+ */
+ EventSharedPtr mpImmediateEvent;
+ };
+
+ /** Generate an interruptable delay event.
+
+ This function generates a pair of events, that are
+ especially tailored to achieve the following behaviour: By
+ default, the given functor is called after the specified
+ timeout (after insertion of the event into the EventQueue,
+ of course). But optionally, when the interruption event
+ InterruptableEventPair::mpImmediateEvent is fired, the
+ given functor is called <em>at once</em>, and the delay is
+ ignored (that means, the given functor is guaranteed to be
+ called at utmost once, and never twice. Furthermore, it is
+ ensured that both events return false on isCharged(), once
+ anyone of them has been fired already).
+
+ @param rFunctor
+ Functor to call when the event fires.
+
+ @param nTimeout
+ Timeout in seconds, to wait until functor is called.
+
+ @returns a pair of events, where the first one waits the
+ specified amount of time, and the other fires the given
+ functor immediately.
+ */
+ template< typename Functor > InterruptableEventPair makeInterruptableDelay( const Functor& rFunctor,
+ double nTimeout )
+ {
+ InterruptableEventPair aRes;
+
+ aRes.mpImmediateEvent = makeEvent( rFunctor, "makeInterruptableDelay");
+ aRes.mpTimeoutEvent.reset( new DelayFacade( aRes.mpImmediateEvent,
+ nTimeout ) );
+
+ return aRes;
+ }
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_INTERRUPTABLEDELAYEVENT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/intrinsicanimationeventhandler.hxx b/slideshow/source/inc/intrinsicanimationeventhandler.hxx
new file mode 100644
index 000000000000..40935d910a23
--- /dev/null
+++ b/slideshow/source/inc/intrinsicanimationeventhandler.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_INTRINSICANIMATIONEVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_INTRINSICANIMATIONEVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+/* Definition of IntrinsicAnimationEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling intrinsic animation display modes.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle intrinsic animation events.
+ */
+ class IntrinsicAnimationEventHandler
+ {
+ public:
+ virtual ~IntrinsicAnimationEventHandler() {}
+
+ virtual bool enableAnimations() = 0;
+ virtual bool disableAnimations() = 0;
+ };
+
+ typedef ::boost::shared_ptr< IntrinsicAnimationEventHandler > IntrinsicAnimationEventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_INTRINSICANIMATIONEVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/listenercontainer.hxx b/slideshow/source/inc/listenercontainer.hxx
new file mode 100644
index 000000000000..533f04ff6420
--- /dev/null
+++ b/slideshow/source/inc/listenercontainer.hxx
@@ -0,0 +1,317 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX
+#define INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX
+
+#include <osl/mutex.hxx>
+#include <boost/utility.hpp>
+#include <algorithm>
+#include <vector>
+
+#include "listenercontainerimpl.hxx"
+
+namespace slideshow {
+namespace internal {
+
+/** Container for objects that can be notified.
+
+ This templatized container holds listener objects, than can get
+ notified (by calling certain methods on them).
+
+ @tpl Listener
+ Type for the listener objects to be held
+
+ @tpl ContainerT
+ Full type of the container to store the listener objects. Defaults
+ to std::vector<ListenerT>
+
+ @tpl MaxDeceasedListenerUllage
+ Threshold, from which upwards the listener container gets
+ pruned. Avoids frequent copying of nearly empty containers.
+
+ @attention internal class, not to be used. functionality is
+ incomplete, please use the Thread(Un)safeListenerContainer types
+ from below
+*/
+template< typename ListenerT,
+ typename MutexHolderBaseT,
+ typename ContainerT=std::vector<ListenerT>,
+ size_t MaxDeceasedListenerUllage=16 > class ListenerContainerBase : public MutexHolderBaseT
+{
+ typedef typename MutexHolderBaseT::Guard Guard;
+ typedef typename MutexHolderBaseT::ClearableGuard ClearableGuard;
+
+public:
+ typedef ListenerT listener_type;
+ typedef ContainerT container_type;
+ typedef MutexHolderBaseT mutex_type;
+
+ /** Check whether listener container is empty
+
+ @return true, if currently no listeners registered. Note that
+ in a multi-threaded scenario, without external synchronisation
+ to this object, the return value might become wrong at any time.
+ */
+ bool isEmpty() const
+ {
+ Guard aGuard(*this);
+ return maListeners.empty();
+ }
+
+ /** Check whether given listener is already added
+
+ @return true, if given listener is already added.
+ */
+ bool isAdded( listener_type const& rListener ) const
+ {
+ Guard aGuard(*this);
+
+ const typename container_type::const_iterator aEnd( maListeners.end() );
+ if( std::find( maListeners.begin(),
+ aEnd,
+ rListener ) != aEnd )
+ {
+ return true; // already added
+ }
+
+ return false;
+ }
+
+ /** Add new listener
+
+ @param rListener
+ Listener to add
+
+ @return false, if the listener is already added, true
+ otherwise
+ */
+ bool add( listener_type const& rListener )
+ {
+ Guard aGuard(*this);
+
+ // ensure uniqueness
+ if( isAdded(rListener) )
+ return false; // already added
+
+ maListeners.push_back( rListener );
+
+ ListenerOperations<ListenerT>::pruneListeners(
+ maListeners,
+ MaxDeceasedListenerUllage);
+
+ return true;
+ }
+
+ /** Add new listener into sorted container
+
+ The stored listeners are kept sorted (using this method
+ requires listener_type to have operator< defined on it). Make
+ sure to call addSorted() for <em>each</em> listener to add to
+ this container - sorting is performed under the assumption
+ that existing entries are already sorted.
+
+ @param rListener
+ Listener to add
+
+ @return false, if the listener is already added, true
+ otherwise
+ */
+ bool addSorted( listener_type const& rListener )
+ {
+ Guard aGuard(*this);
+
+ // ensure uniqueness
+ if( isAdded(rListener) )
+ return false; // already added
+
+ maListeners.push_back( rListener );
+
+ // a single entry does not need to be sorted
+ if( maListeners.size() > 1 )
+ {
+ std::inplace_merge(
+ maListeners.begin(),
+ boost::prior(maListeners.end()),
+ maListeners.end() );
+ }
+
+ ListenerOperations<ListenerT>::pruneListeners(
+ maListeners,
+ MaxDeceasedListenerUllage);
+
+ return true;
+ }
+
+ /** Remove listener from container
+
+ @param rListener
+ The listener to remove
+
+ @return false, if listener not found in container, true
+ otherwise
+ */
+ bool remove( listener_type const& rListener )
+ {
+ Guard aGuard(*this);
+
+ const typename container_type::iterator aEnd( maListeners.end() );
+ typename container_type::iterator aIter;
+ if( (aIter=std::remove(maListeners.begin(),
+ aEnd,
+ rListener)) == aEnd )
+ {
+ return false; // listener not found
+ }
+
+ maListeners.erase( aIter, aEnd );
+
+ return true;
+ }
+
+ /// Removes all listeners in one go
+ void clear()
+ {
+ Guard aGuard(*this);
+
+ maListeners.clear();
+ }
+
+ /** Apply functor to one listener
+
+ This method applies functor to one of the listeners. Starting
+ with the first entry of the container, the functor is called
+ with the listener entries, until it returns true.
+
+ @param func
+ Given functor is called with listeners, until it returns true
+
+ @return true, if functor was successfully applied to a
+ listener
+ */
+ template< typename FuncT > bool apply( FuncT func ) const
+ {
+ ClearableGuard aGuard(*this);
+
+ // generate a local copy of all handlers, to make method
+ // reentrant and thread-safe.
+ container_type const local( maListeners );
+ aGuard.clear();
+
+ const bool bRet(
+ ListenerOperations<ListenerT>::notifySingleListener(
+ local,
+ func ));
+
+ {
+ Guard aGuard2(*this);
+ ListenerOperations<ListenerT>::pruneListeners(
+ const_cast<container_type&>(maListeners),
+ MaxDeceasedListenerUllage);
+ }
+
+ return bRet;
+ }
+
+ /** Apply functor to all listeners
+
+ This method applies functor to all of the listeners. Starting
+ with the first entry of the container, the functor is called
+ with the listener entries.
+
+ @param func
+ Given functor is called with listeners.
+
+ @return true, if functor was successfully applied to at least
+ one listener
+ */
+ template< typename FuncT > bool applyAll( FuncT func ) const
+ {
+ ClearableGuard aGuard(*this);
+
+ // generate a local copy of all handlers, to make method
+ // reentrant and thread-safe.
+ container_type const local( maListeners );
+ aGuard.clear();
+
+ const bool bRet(
+ ListenerOperations<ListenerT>::notifyAllListeners(
+ local,
+ func ));
+
+ {
+ Guard aGuard2(*this);
+ ListenerOperations<ListenerT>::pruneListeners(
+ const_cast<container_type&>(maListeners),
+ MaxDeceasedListenerUllage);
+ }
+
+ return bRet;
+ }
+
+private:
+ ContainerT maListeners;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+/** ListenerContainer variant that serialized access
+
+ This ListenerContainer is safe to use in a multi-threaded
+ context. It serializes access to the object, and avoids
+ dead-locking by releasing the object mutex before calling
+ listeners.
+ */
+template< typename ListenerT,
+ typename ContainerT=std::vector<ListenerT> >
+class ThreadSafeListenerContainer : public ListenerContainerBase<ListenerT,
+ MutexBase,
+ ContainerT>
+{
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+/** ListenerContainer variant that does not serialize access
+
+ This ListenerContainer version is not safe to use in a
+ multi-threaded scenario, but has less overhead.
+ */
+template< typename ListenerT,
+ typename ContainerT=std::vector<ListenerT> >
+class ThreadUnsafeListenerContainer : public ListenerContainerBase<ListenerT,
+ EmptyBase,
+ ContainerT>
+{
+};
+
+} // namespace internal
+} // namespace slideshow
+
+#endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/listenercontainerimpl.hxx b/slideshow/source/inc/listenercontainerimpl.hxx
new file mode 100644
index 000000000000..cecffec7b647
--- /dev/null
+++ b/slideshow/source/inc/listenercontainerimpl.hxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_LISTENERCONTAINERIMPL_HXX
+#define INCLUDED_SLIDESHOW_LISTENERCONTAINERIMPL_HXX
+
+#include <sal/config.h>
+#include <boost/weak_ptr.hpp>
+
+namespace slideshow {
+namespace internal {
+
+////////////////////////////////////////////////////////////////////////////
+
+struct EmptyBase
+{
+ struct EmptyGuard{ explicit EmptyGuard(EmptyBase) {} };
+ struct EmptyClearableGuard
+ {
+ explicit EmptyClearableGuard(EmptyBase) {}
+ void clear() {}
+ void reset() {}
+ };
+
+ typedef EmptyGuard Guard;
+ typedef EmptyClearableGuard ClearableGuard;
+};
+
+class MutexBase
+{
+public:
+ struct Guard : public osl::MutexGuard
+ {
+ explicit Guard(MutexBase const& rBase) :
+ osl::MutexGuard(rBase.maMutex)
+ {}
+ };
+ struct ClearableGuard : public osl::ClearableMutexGuard
+ {
+ explicit ClearableGuard(MutexBase const& rBase) :
+ osl::ClearableMutexGuard(rBase.maMutex)
+ {}
+ };
+
+ mutable osl::Mutex maMutex;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+template< typename result_type, typename ListenerTargetT > struct FunctionApply
+{
+ template<typename FuncT> static bool apply(
+ FuncT func,
+ ListenerTargetT const& rArg )
+ {
+ return func(rArg);
+ }
+};
+
+template<typename ListenerTargetT> struct FunctionApply<void,ListenerTargetT>
+{
+ template<typename FuncT> static bool apply(
+ FuncT func,
+ ListenerTargetT const& rArg )
+ {
+ func(rArg);
+ return true;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+template< typename ListenerT > struct ListenerOperations
+{
+ /// Notify a single one of the listeners
+ template< typename ContainerT,
+ typename FuncT >
+ static bool notifySingleListener( ContainerT& rContainer,
+ FuncT func )
+ {
+ const typename ContainerT::const_iterator aEnd( rContainer.end() );
+
+ // true: a handler in this queue processed the event
+ // false: no handler in this queue finally processed the event
+ return (std::find_if( rContainer.begin(),
+ aEnd,
+ func ) != aEnd);
+ }
+
+ /// Notify all listeners
+ template< typename ContainerT,
+ typename FuncT >
+ static bool notifyAllListeners( ContainerT& rContainer,
+ FuncT func )
+ {
+ bool bRet(false);
+ typename ContainerT::const_iterator aCurr( rContainer.begin() );
+ typename ContainerT::const_iterator const aEnd ( rContainer.end() );
+ while( aCurr != aEnd )
+ {
+ if( FunctionApply< typename FuncT::result_type,
+ typename ContainerT::value_type >::apply(
+ func,
+ *aCurr) )
+ {
+ bRet = true;
+ }
+
+ ++aCurr;
+ }
+
+ // true: at least one handler returned true
+ // false: not a single handler returned true
+ return bRet;
+ }
+
+ /// Prune container from deceased listeners
+ template< typename ContainerT >
+ static void pruneListeners( ContainerT&, size_t )
+ {
+ }
+};
+
+// specializations for weak_ptr
+// ----------------------------
+template< typename ListenerTargetT >
+struct ListenerOperations< boost::weak_ptr<ListenerTargetT> >
+{
+ template< typename ContainerT,
+ typename FuncT >
+ static bool notifySingleListener( ContainerT& rContainer,
+ FuncT func )
+ {
+ typename ContainerT::const_iterator aCurr( rContainer.begin() );
+ typename ContainerT::const_iterator const aEnd ( rContainer.end() );
+ while( aCurr != aEnd )
+ {
+ boost::shared_ptr<ListenerTargetT> pListener( aCurr->lock() );
+
+ if( pListener && func(pListener) )
+ return true;
+
+ ++aCurr;
+ }
+
+ return false;
+ }
+
+ template< typename ContainerT,
+ typename FuncT >
+ static bool notifyAllListeners( ContainerT& rContainer,
+ FuncT func )
+ {
+ bool bRet(false);
+ typename ContainerT::const_iterator aCurr( rContainer.begin() );
+ typename ContainerT::const_iterator const aEnd ( rContainer.end() );
+ while( aCurr != aEnd )
+ {
+ boost::shared_ptr<ListenerTargetT> pListener( aCurr->lock() );
+
+ if( pListener.get() &&
+ FunctionApply< typename FuncT::result_type,
+ boost::shared_ptr<ListenerTargetT> >::apply(func,pListener) )
+ {
+ bRet = true;
+ }
+
+ ++aCurr;
+ }
+
+ return bRet;
+ }
+
+ template< typename ContainerT >
+ static void pruneListeners( ContainerT& rContainer,
+ size_t nSizeThreshold )
+ {
+ if( rContainer.size() <= nSizeThreshold )
+ return;
+
+ ContainerT aAliveListeners;
+ aAliveListeners.reserve(rContainer.size());
+
+ typename ContainerT::const_iterator aCurr( rContainer.begin() );
+ typename ContainerT::const_iterator const aEnd ( rContainer.end() );
+ while( aCurr != aEnd )
+ {
+ if( !aCurr->expired() )
+ aAliveListeners.push_back( *aCurr );
+
+ ++aCurr;
+ }
+
+ std::swap( rContainer, aAliveListeners );
+ }
+};
+
+} // namespace internal
+} // namespace Presentation
+
+#endif /* INCLUDED_SLIDESHOW_LISTENERCONTAINERIMPL_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/mouseeventhandler.hxx b/slideshow/source/inc/mouseeventhandler.hxx
new file mode 100644
index 000000000000..f601490cde4a
--- /dev/null
+++ b/slideshow/source/inc/mouseeventhandler.hxx
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_MOUSEEVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_MOUSEEVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star { namespace awt
+{
+ struct MouseEvent;
+} } } }
+
+
+/* Definition of MouseEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling mouse events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle mouse events.
+ */
+ class MouseEventHandler
+ {
+ public:
+ virtual ~MouseEventHandler() {}
+
+ /** Handle a mouse button pressed event.
+
+ @param e
+ The mouse event that occurred. The x,y coordinates of
+ the event are already transformed back to user
+ coordinate space, taking the inverse transform of the
+ view in which the event occurred.
+
+ @return true, if this handler has successfully
+ processed the mouse event. When this method returns
+ false, possibly other, less prioritized handlers can be
+ called, too.
+ */
+ virtual bool handleMousePressed( const ::com::sun::star::awt::MouseEvent& e ) = 0;
+
+ /** Handle a mouse button released event.
+
+ @param e
+ The mouse event that occurred. The x,y coordinates of
+ the event are already transformed back to user
+ coordinate space, taking the inverse transform of the
+ view in which the event occurred.
+
+ @return true, if this handler has successfully
+ processed the pause event. When this method returns
+ false, possibly other, less prioritized handlers are
+ called, too.
+ */
+ virtual bool handleMouseReleased( const ::com::sun::star::awt::MouseEvent& e ) = 0;
+
+ /** Handle a mouse entered the view event.
+
+ @param e
+ The mouse event that occurred. The x,y coordinates of
+ the event are already transformed back to user
+ coordinate space, taking the inverse transform of the
+ view in which the event occurred.
+
+ @return true, if this handler has successfully
+ processed the pause event. When this method returns
+ false, possibly other, less prioritized handlers are
+ called, too.
+ */
+ virtual bool handleMouseEntered( const ::com::sun::star::awt::MouseEvent& e ) = 0;
+
+ /** Handle a mouse exited the view event.
+
+ @param e
+ The mouse event that occurred. The x,y coordinates of
+ the event are already transformed back to user
+ coordinate space, taking the inverse transform of the
+ view in which the event occurred.
+
+ @return true, if this handler has successfully
+ processed the pause event. When this method returns
+ false, possibly other, less prioritized handlers are
+ called, too.
+ */
+ virtual bool handleMouseExited( const ::com::sun::star::awt::MouseEvent& e ) = 0;
+
+ /** Handle a mouse was moved with a pressed button event.
+
+ @param e
+ The mouse event that occurred. The x,y coordinates of
+ the event are already transformed back to user
+ coordinate space, taking the inverse transform of the
+ view in which the event occurred.
+
+ @return true, if this handler has successfully
+ processed the pause event. When this method returns
+ false, possibly other, less prioritized handlers are
+ called, too.
+ */
+ virtual bool handleMouseDragged( const ::com::sun::star::awt::MouseEvent& e ) = 0;
+
+ /** Handle a mouse was moved event.
+
+ @param e
+ The mouse event that occurred. The x,y coordinates of
+ the event are already transformed back to user
+ coordinate space, taking the inverse transform of the
+ view in which the event occurred.
+
+ @return true, if this handler has successfully
+ processed the pause event. When this method returns
+ false, possibly other, less prioritized handlers are
+ called, too.
+ */
+ virtual bool handleMouseMoved( const ::com::sun::star::awt::MouseEvent& e ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< MouseEventHandler > MouseEventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_MOUSEEVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/numberanimation.hxx b/slideshow/source/inc/numberanimation.hxx
new file mode 100644
index 000000000000..b841ef1c865e
--- /dev/null
+++ b/slideshow/source/inc/numberanimation.hxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_NUMBERANIMATION_HXX
+#define INCLUDED_SLIDESHOW_NUMBERANIMATION_HXX
+
+#include <animation.hxx>
+
+
+/* Definition of NumberAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a number animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes representable
+ by a single floating point value.
+ */
+ class NumberAnimation : public Animation
+ {
+ public:
+ typedef double ValueType;
+
+ /** Set the animation to value x
+
+ @param x
+ Current animation value (must be in an
+ attribute-specific permissible range). Overflowing
+ values will be clipped to the permissible range
+ internally.
+ */
+ virtual bool operator()( ValueType x ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< NumberAnimation > NumberAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_NUMBERANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/pairanimation.hxx b/slideshow/source/inc/pairanimation.hxx
new file mode 100644
index 000000000000..c913a338df7e
--- /dev/null
+++ b/slideshow/source/inc/pairanimation.hxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_PAIRANIMATION_HXX
+#define INCLUDED_SLIDESHOW_PAIRANIMATION_HXX
+
+#include "animation.hxx"
+#include <basegfx/tuple/b2dtuple.hxx>
+
+
+/* Definition of PairAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a pair of numbers animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes representable
+ by a pair of floating point values (e.g. a position or a
+ size).
+ */
+ class PairAnimation : public Animation
+ {
+ public:
+ typedef ::basegfx::B2DTuple ValueType;
+
+ /** Set the animation to the given value
+
+ @param rValue
+ Current animation value.
+ */
+ virtual bool operator()( const ValueType& rValue ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< PairAnimation > PairAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_PAIRANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/pauseeventhandler.hxx b/slideshow/source/inc/pauseeventhandler.hxx
new file mode 100644
index 000000000000..144f9c45ee72
--- /dev/null
+++ b/slideshow/source/inc/pauseeventhandler.hxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_PAUSEEVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_PAUSEEVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of PauseHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling pause events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle pause events.
+ */
+ class PauseEventHandler
+ {
+ public:
+ /** Handle the event.
+
+ @param bPauseShow
+ When true, the show is paused. When false, the show is
+ started again
+
+ @return true, if this handler has successfully
+ processed the pause event. When this method returns
+ false, possibly other, less prioritized handlers are
+ called, too.
+ */
+ virtual bool handlePause( bool bPauseShow ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< PauseEventHandler > PauseEventHandlerSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_PAUSEEVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/rgbcolor.hxx b/slideshow/source/inc/rgbcolor.hxx
new file mode 100644
index 000000000000..fd27859b305f
--- /dev/null
+++ b/slideshow/source/inc/rgbcolor.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_RGBCOLOR_HXX
+#define INCLUDED_SLIDESHOW_RGBCOLOR_HXX
+
+#include <cppcanvas/color.hxx>
+
+
+/* Definition of RGBColor class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class HSLColor;
+
+ /** RGB color space class.
+ */
+ class RGBColor
+ {
+ public:
+ RGBColor();
+ explicit RGBColor( ::cppcanvas::Color::IntSRGBA nRGBColor );
+ RGBColor( double nRed, double nGreen, double nBlue );
+ explicit RGBColor( const HSLColor& rColor );
+
+ /** Hue of the color.
+
+ @return hue, is in the range [0,360]
+ */
+ double getHue() const;
+
+ /** Saturation of the color.
+
+ @return saturation, is in the range [0,1]
+ */
+ double getSaturation() const;
+
+ /** Luminance of the color.
+
+ @return luminance, is in the range [0,1]
+ */
+ double getLuminance() const;
+
+ /** Get the RGB red value.
+ */
+ double getRed() const;
+
+ /** Get the RGB green value.
+ */
+ double getGreen() const;
+
+ /** Get the RGB blue value.
+ */
+ double getBlue() const;
+
+ /** Create an HSL color object.
+ */
+ HSLColor getHSLColor() const;
+
+ /** Create an integer sRGBA color.
+ */
+ ::cppcanvas::Color::IntSRGBA getIntegerColor() const;
+
+ RGBColor(const RGBColor& rLHS);
+ RGBColor& operator=( const RGBColor& rLHS);
+
+ struct RGBTriple
+ {
+ RGBTriple();
+ RGBTriple( double nRed, double nGreen, double nBlue );
+
+ double mnRed;
+ double mnGreen;
+ double mnBlue;
+ };
+
+ private:
+ // default copy/assignment are okay
+ // RGBColor(const RGBColor&);
+ // RGBColor& operator=( const RGBColor& );
+
+ RGBTriple maRGBTriple;
+ };
+
+ RGBColor operator+( const RGBColor& rLHS, const RGBColor& rRHS );
+ RGBColor operator*( const RGBColor& rLHS, const RGBColor& rRHS );
+ RGBColor operator*( double nFactor, const RGBColor& rRHS );
+
+
+ /** RGB color linear interpolator.
+
+ @param t
+ As usual, t must be in the [0,1] range
+ */
+ RGBColor interpolate( const RGBColor& rFrom, const RGBColor& rTo, double t );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_RGBCOLOR_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/screenupdater.hxx b/slideshow/source/inc/screenupdater.hxx
new file mode 100644
index 000000000000..d2ce2a4f054e
--- /dev/null
+++ b/slideshow/source/inc/screenupdater.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SCREENUPDATER_HXX
+#define INCLUDED_SLIDESHOW_SCREENUPDATER_HXX
+
+#include "viewupdate.hxx"
+#include "unoviewcontainer.hxx"
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+
+/* Definition of ScreenUpdater class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Screen updater
+
+ This class handles and synchronizes screen updates
+ centrally. Therefore, it can hold a number of ViewUpdate
+ objects, which are polled for pending updates on
+ commitUpdates(). Furthermore, external code can request
+ updates via notifyUpdate() calls. If neither such an
+ update was requested, nor any of the registered ViewUpdate
+ objects report any pending update, commitUpdates() does
+ nothing.
+ */
+ class ScreenUpdater : boost::noncopyable
+ {
+ public:
+ explicit ScreenUpdater( UnoViewContainer const& rViewContainer );
+ ~ScreenUpdater();
+
+ /** Notify screen update
+
+ This method records a screen content update request
+ for all views.
+ */
+ void notifyUpdate();
+
+ /** Notify screen update
+
+ This method records a screen content update request
+ for the given view.
+
+ @param rView
+ The view that needs an update
+
+ @param bViewClobbered
+ When true, notifies update that view content is
+ clobbered by external circumstances (e.g. by another
+ application), and needs update even if the
+ implementation 'thinks' it does not need to render
+ something to screen.
+ */
+ void notifyUpdate( const UnoViewSharedPtr& rView, bool bViewClobbered=false );
+
+ /** Commits collected update actions
+ */
+ void commitUpdates();
+
+ /** Register ViewUpdate
+
+ @param rViewUpdate
+ Add this ViewUpdate to the list that's asked for
+ pending updates
+ */
+ void addViewUpdate( ViewUpdateSharedPtr const& rViewUpdate );
+
+ /** Unregister ViewUpdate
+
+ @param rViewUpdate
+ Remove this ViewUpdate from the list that's asked for
+ pending updates
+ */
+ void removeViewUpdate( ViewUpdateSharedPtr const& );
+
+ /** A wart.
+
+ Used to fire an immediate screen update. Currently
+ needed for the wait symbol, since switching that on
+ and off does get to commitUpdates()
+ */
+ void requestImmediateUpdate();
+
+ class UpdateLock {public: virtual void Activate (void) = 0; };
+
+ /** Call this method to create a lock instead of calling
+ lockUpdates() and unlockUpdates() directly.
+ @param bStartLocked
+ When <TRUE/> then the UpdateLock is created already
+ locked. When <FALSE/> then Activate() has to be called in order
+ to lock the lock.
+ */
+ ::boost::shared_ptr<UpdateLock> createLock (const bool bStartLocked);
+
+ /** Lock updates to prevent intermediate repaints.
+ */
+ void lockUpdates (void);
+
+ /** When called as often as lockUpdates() then commitUpdates()
+ is called.
+ */
+ void unlockUpdates (void);
+
+ private:
+ struct ImplScreenUpdater;
+ boost::scoped_ptr<ImplScreenUpdater> mpImpl;
+
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SCREENUPDATER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shape.hxx b/slideshow/source/inc/shape.hxx
new file mode 100644
index 000000000000..74ea15921634
--- /dev/null
+++ b/slideshow/source/inc/shape.hxx
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPE_HXX
+#define INCLUDED_SLIDESHOW_SHAPE_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+
+#include <basegfx/range/b2drectangle.hxx>
+
+#include "viewlayer.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <set>
+#include <vector>
+
+namespace basegfx {
+ class B2DRange;
+}
+
+namespace slideshow
+{
+ namespace internal
+ {
+ // forward declaration necessary, because methods use ShapeSharedPtr
+ class Shape;
+
+ typedef ::boost::shared_ptr< Shape > ShapeSharedPtr;
+
+ /** Represents a slide's shape object.
+
+ This interface represents the view-independent aspects of a
+ slide's shape, providing bound rect, underlying XShape and
+ basic paint methods.
+ */
+ class Shape : private boost::noncopyable
+ {
+ public:
+ virtual ~Shape() {}
+
+ /** Get the associated XShape of this shape.
+
+ @return the associated XShape. If this method returns
+ an empty reference, this object might be one of the
+ special-purpose shapes of a slide, which have no
+ direct corresponding XShape (the background comes to
+ mind here).
+ */
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > getXShape() const = 0;
+
+
+ // View layer methods
+ //------------------------------------------------------------------
+
+ /** Add a new view layer.
+
+ This method adds a new view layer, this shape shall
+ show itself on.
+
+ @param rNewLayer
+ New layer to show on
+
+ @param bRedrawLayer
+ Redraw shape on given layer
+ */
+ virtual void addViewLayer( const ViewLayerSharedPtr& rNewLayer,
+ bool bRedrawLayer ) = 0;
+
+ /** Withdraw the shape from a view layer
+
+ This method removes the shape from the given view
+ layer.
+
+ @return true, if the shape was successfully removed
+ */
+ virtual bool removeViewLayer( const ViewLayerSharedPtr& rNewLayer ) = 0;
+
+ /** Withdraw all view layers at once
+
+ This method will be faster than repeated
+ removeViewLayer() calls.
+ */
+ virtual bool clearAllViewLayers() = 0;
+
+ // render methods
+ //------------------------------------------------------------------
+
+ /** Update the shape
+
+ This method updates the Shape on all registered view
+ layers, but only if shape content has actually
+ changed.
+
+ @return whether the update finished successfully.
+ */
+ virtual bool update() const = 0;
+
+ /** Render the shape.
+
+ This method renders the shape on all registered view
+ layers, regardless of whether shape content has
+ changed or not.
+
+ @return whether the rendering finished successfully.
+ */
+ virtual bool render() const = 0;
+
+ /** Query whether shape content changed
+
+ This method returns true, if shape content changed
+ since the last rendering (i.e. the shape needs an
+ update to reflect that changed content on the views).
+ */
+ virtual bool isContentChanged() const = 0;
+
+
+ // Shape attributes
+ //------------------------------------------------------------------
+
+ /** Get the current shape position and size.
+
+ This method yields the currently effective shape
+ bounds (which might change over time, for animated
+ shapes). Please note that possibly shape rotations
+ from its original document state must not be taken
+ into account here: if you need the screen bounding
+ box, use getUpdateArea() instead. Note further that
+ shape rotations, which are already contained in the
+ shape as displayed in the original document
+ <em>are</em> included herein (we currently take the
+ shape as-is from the document, assuming a rotation
+ angle of 0).
+ */
+ virtual ::basegfx::B2DRange getBounds() const = 0;
+
+ /** Get the DOM position and size of the shape.
+
+ This method yields the underlying DOM shape bounds,
+ i.e. the original shape bounds from the document
+ model. This value is <em>always</em> unaffected by any
+ animation activity. Note that shape rotations, which
+ are already contained in the shape as displayed in the
+ original document are already included herein (we
+ currently take the shape as-is from the document,
+ assuming a rotation angle of 0).
+ */
+ virtual ::basegfx::B2DRange getDomBounds() const = 0;
+
+ /** Get the current shape update area.
+
+ This method yields the currently effective update area
+ for the shape, i.e. the area that needs to be updated,
+ should the shape be painted. Normally, this will be
+ the (possibly rotated and sheared) area returned by
+ getBounds().
+ */
+ virtual ::basegfx::B2DRange getUpdateArea() const = 0;
+
+ /** Query whether the shape is visible at all.
+
+ @return true, if this shape is visible, false
+ otherwise.
+ */
+ virtual bool isVisible() const = 0;
+
+ /** Get the shape priority.
+
+ The shape priority defines the relative order of the
+ shapes on the slide.
+
+ @return the priority. Will be in the [0,+infty) range.
+ */
+ virtual double getPriority() const = 0;
+
+ /** Query whether the Shape is currently detached from the
+ background.
+
+ This method checks whether the Shape is currently
+ detached from the slide background, i.e. whether shape
+ updates affect the underlying slide background or
+ not. A shape that returnes true here must not alter
+ slide content in any way when called render() or
+ update() (this is normally achieved by making this
+ shape a sprite).
+ */
+ virtual bool isBackgroundDetached() const = 0;
+
+ // Misc
+ //------------------------------------------------------------------
+
+ /** Functor struct, for shape ordering
+
+ This defines a strict weak ordering of shapes, primary
+ sort key is the shape priority, and secondy sort key
+ the object ptr value. Most typical use is for
+ associative containers holding shapes (and which also
+ have to maintain something like a paint order).
+ */
+ struct lessThanShape
+ {
+ // make functor adaptable (to boost::bind)
+ typedef bool result_type;
+
+ // since the ZOrder property on the XShape has somewhat
+ // peculiar attributes (it's basically the index of the shapes
+ // in the drawing layer's SdrObjList - which means, it starts
+ // from 0 for children of group objects), we cannot use it to determine
+ // drawing order. Thus, we rely on importer-provided order values here,
+ // which is basically a running counter during shape import (i.e. denotes
+ // the order of shape import). This is the correct order, at least for the
+ // current drawing core.
+ //
+ // If, someday, the above proposition is no longer true, one directly use
+ // the shape's ZOrder property
+ //
+ static bool compare(const Shape* pLHS, const Shape* pRHS)
+ {
+ const double nPrioL( pLHS->getPriority() );
+ const double nPrioR( pRHS->getPriority() );
+
+ // if prios are equal, tie-break on ptr value
+ return nPrioL == nPrioR ? pLHS < pRHS : nPrioL < nPrioR;
+ }
+
+ bool operator()(const ShapeSharedPtr& rLHS, const ShapeSharedPtr& rRHS) const
+ {
+ return compare(rLHS.get(),rRHS.get());
+ }
+
+ bool operator()(const Shape* pLHS, const Shape* pRHS) const
+ {
+ return compare(pLHS, pRHS);
+ }
+ };
+ };
+
+ typedef ::boost::shared_ptr< Shape > ShapeSharedPtr;
+
+ /** A set which contains all shapes in an ordered fashion.
+ */
+ typedef ::std::set< ShapeSharedPtr, Shape::lessThanShape > ShapeSet;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapeattributelayer.hxx b/slideshow/source/inc/shapeattributelayer.hxx
new file mode 100644
index 000000000000..73346430abd3
--- /dev/null
+++ b/slideshow/source/inc/shapeattributelayer.hxx
@@ -0,0 +1,559 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPEATTRIBUTELAYER_HXX
+#define INCLUDED_SLIDESHOW_SHAPEATTRIBUTELAYER_HXX
+
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+
+#include <basegfx/vector/b2dsize.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include "state.hxx"
+#include "rgbcolor.hxx"
+
+#include <stack>
+#include <boost/shared_ptr.hpp>
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class ShapeAttributeLayer;
+
+ typedef ::boost::shared_ptr< ShapeAttributeLayer > ShapeAttributeLayerSharedPtr;
+
+ /** Encapsulates all modifiable attributes of a shape.
+
+ This class holds all modifiable attributes of a shape, and
+ at the same time provides means to layer attributes on top
+ of each other..
+
+ And yes, there's a reason why we even pass bools and ints
+ by const reference. Namely, that makes the set* methods
+ differ only in the value type, which greatly reduces
+ template variability (e.g. in AnimationFactory).
+ */
+ class ShapeAttributeLayer
+ {
+ public:
+ /** Create a ShapeAttributeLayer instance, with all
+ attributes set to default.
+
+ Furthermore, this constructor gets a pointer to a
+ child layer, which is used as the fallback (or the
+ base value) for all attributes
+
+ @param rChildLayer
+ Layer below this one
+
+ @attention
+ This method is only supposed to be called from Shape objects
+ */
+ explicit ShapeAttributeLayer( const ShapeAttributeLayerSharedPtr& rChildLayer );
+
+ // Children management methods
+ //------------------------------------------------------------------
+
+ /** Revoke the given layer.
+
+ This method revokes the given layer from this object
+ or one of the children. That is, if this object does
+ have children, and the given layer is no direct child,
+ it is recursively passed to the children for removal.
+
+ @return true, if removal was successful.
+
+ @attention
+ This method is only supposed to be called from Shape objects
+ */
+ bool revokeChildLayer( const ShapeAttributeLayerSharedPtr& rChildLayer );
+
+ /** Query the child layer of this object.
+
+ @attention
+ This method is only supposed to be called from Shape objects
+ */
+ ShapeAttributeLayerSharedPtr getChildLayer() const;
+
+ /** Set the additive mode for possible child attributes
+
+ This method sets the additive mode for child
+ attributes. That is the way underlying attribute
+ layers are combined with this one (i.e. to overrule
+ lower layers, or how to combine the values). The
+ default is
+ ::com::sun::star::animations::AnimationAdditiveMode::BASE,
+ which means, take the value of the underlying layers,
+ or from the model shape itself.
+
+ @param nMode
+ Must be one of
+ ::com::sun::star::animations::AnimationAdditiveMode.
+ */
+ void setAdditiveMode( sal_Int16 nMode );
+
+ // Attribute methods
+ //------------------------------------------------------------------
+
+ /** Query whether the width attribute is valid.
+ */
+ bool isWidthValid() const;
+ /** Query the current width of the shape
+ */
+ double getWidth() const;
+ /** Set the new width of the shape
+
+ @param rNewWidth
+ A negative width mirrors the shape.
+ */
+ void setWidth( const double& rNewWidth );
+
+ /** Query whether the height attribute is valid.
+ */
+ bool isHeightValid() const;
+ /** Query the current height of the shape
+ */
+ double getHeight() const;
+ /** Set the new height of the shape
+
+ @param rNewHeight
+ A negative height mirrors the shape.
+ */
+ void setHeight( const double& rNewHeight );
+
+ /** Set the new size of the shape
+
+ @param rNewSize
+ A negative size mirrors the shape.
+ */
+ void setSize( const ::basegfx::B2DSize& rNewSize );
+
+ /** Query whether the x position attribute is valid
+ */
+ bool isPosXValid() const;
+ /** Query the current x position of the shape.
+
+ The current x position of the shape is always relative
+ to the <em>center</em> of the shape (in contrast to
+ the Shape::getBounds() and Shape::getUpdateArea()
+ methods).
+ */
+ double getPosX() const;
+ /** Set the new x position of the shape
+
+ The current x position of the shape is always relative
+ to the <em>center</em> of the shape (in contrast to
+ the Shape::getBounds() and Shape::getUpdateArea()
+ methods).
+ */
+ void setPosX( const double& rNewX );
+
+ /** Query whether the y position attribute is valid
+ */
+ bool isPosYValid() const;
+ /** Query the current y position of the shape
+
+ The current y position of the shape is always relative
+ to the <em>center</em> of the shape (in contrast to
+ the Shape::getBounds() and Shape::getUpdateArea()
+ methods).
+ */
+ double getPosY() const;
+ /** Set the new y position of the shape
+
+ The current y position of the shape is always relative
+ to the <em>center</em> of the shape (in contrast to
+ the Shape::getBounds() and Shape::getUpdateArea()
+ methods).
+ */
+ void setPosY( const double& rNewY );
+
+ /** Set the new position of the shape
+
+ The current position of the shape is always relative
+ to the <em>center</em> of the shape (in contrast to
+ the Shape::getBounds() and Shape::getUpdateArea()
+ methods).
+ */
+ void setPosition( const ::basegfx::B2DPoint& rNewPos );
+
+ /** Query whether the rotation angle attribute is valid
+ */
+ bool isRotationAngleValid() const;
+ /** Query the current rotation angle of the shape
+
+ @return the rotation angle in degrees.
+ */
+ double getRotationAngle() const;
+ /** Set the new rotation angle of the shape
+
+ @param rNewAngle
+ New rotation angle in degrees.
+ */
+ void setRotationAngle( const double& rNewAngle );
+
+ /** Query whether the shear x angle attribute is valid
+ */
+ bool isShearXAngleValid() const;
+ /** Query the current shear angle at the x axis of the shape
+
+ @return the shear angle in degrees.
+ */
+ double getShearXAngle() const;
+ /** Set the new shear angle at the x axis of the shape
+
+ @param rNewAngle
+ New shear angle in radians.
+ */
+ void setShearXAngle( const double& rNewAngle );
+
+ /** Query whether the shear y angle attribute is valid
+ */
+ bool isShearYAngleValid() const;
+ /** Query the current shear angle at the y axis of the shape
+
+ @return the shear angle in degrees.
+ */
+ double getShearYAngle() const;
+ /** Set the new shear angle at the y axis of the shape
+
+ @param rNewAngle
+ New shear angle in radians.
+ */
+ void setShearYAngle( const double& rNewAngle );
+
+ /** Query whether the alpha attribute is valid
+ */
+ bool isAlphaValid() const;
+ /** Query the current alpha value of the shape
+ */
+ double getAlpha() const;
+ /** Set the new alpha value of the shape
+
+ @param rNewValue
+ New alpha value, must be in the [0,1] range
+ */
+ void setAlpha( const double& rNewValue );
+
+ /** Query whether the clip attribute is valid
+ */
+ bool isClipValid() const;
+ /** Query the current clip polygon of the shape
+ */
+ ::basegfx::B2DPolyPolygon getClip() const;
+ /** Set the new clip polygon of the shape
+
+ @param rNewClip
+ New clip polygon, is interpreted in shape view coordinates, but
+ relative to the shape (i.e. the origin of the shape coincides
+ with the origin of the clip polygon).
+ */
+ void setClip( const ::basegfx::B2DPolyPolygon& rNewClip );
+
+ /** Query whether the dim color attribute is valid
+
+ The dim color globally 'dims' the shape towards that
+ color
+ */
+ bool isDimColorValid() const;
+ /** Get the dim color for the whole shape.
+ */
+ RGBColor getDimColor() const;
+ /** Set the dim color globally for the whole shape.
+ */
+ void setDimColor( const RGBColor& nNewColor );
+
+ /** Query whether the fill color attribute is valid
+ */
+ bool isFillColorValid() const;
+ /** Get the fill color for the whole shape.
+
+ If there's no unique fill color, the color from the
+ first filled polygon is returned.
+ */
+ RGBColor getFillColor() const;
+ /** Set the fill color globally for the whole shape.
+ */
+ void setFillColor( const RGBColor& nNewColor );
+
+ /** Query whether the line color attribute is valid
+ */
+ bool isLineColorValid() const;
+ /** Get the line color for the whole shape.
+
+ If there's no unique line color, the color from the
+ first line is returned.
+ */
+ RGBColor getLineColor() const;
+ /** Set the line color globally for the whole shape.
+ */
+ void setLineColor( const RGBColor& nNewColor );
+
+ /** Query whether the fill mode attribute is valid
+ */
+ bool isFillStyleValid() const;
+ /** Get the current fill mode for polygon fillings.
+
+ @returns the current style
+ */
+ sal_Int16 getFillStyle() const;
+ /** Changes polygon fillings.
+ */
+ void setFillStyle( const sal_Int16& rStyle );
+
+ /** Query whether the line mode attribute is valid
+ */
+ bool isLineStyleValid() const;
+ /** Get the current line mode for line drawing.
+
+ @returns the current line style
+ */
+ sal_Int16 getLineStyle() const;
+ /** Set line style for the whole shape
+ */
+ void setLineStyle( const sal_Int16& rStyle );
+
+ /** Query whether the visibility state attribute is valid
+ */
+ bool isVisibilityValid() const;
+ /** Get the current shape visibility.
+
+ @returns true for visible, false for invisible.
+ */
+ bool getVisibility() const;
+ /** Set the shape visibility
+ */
+ void setVisibility( const bool& bVisible );
+
+ /** Query whether the char color attribute is valid
+ */
+ bool isCharColorValid() const;
+ /** Get the text color for the whole shape.
+
+ If there's no unique text color, the color from the
+ first text drawn is returned.
+ */
+ RGBColor getCharColor() const;
+ /** Set the text color globally for the whole shape.
+ */
+ void setCharColor( const RGBColor& nNewColor );
+
+ /** Query whether the char rotation angle attribute is valid
+ */
+ bool isCharRotationAngleValid() const;
+ /** Query the current text rotation angle of the shape
+
+ @return the text rotation angle in degrees.
+ */
+ double getCharRotationAngle() const;
+ /** Set the new text rotation angle of the shape
+
+ @param rNewAngle
+ New text rotation angle in degrees.
+ */
+ void setCharRotationAngle( const double& rNewAngle );
+
+ /** Query whether the char weight attribute is valid
+ */
+ bool isCharWeightValid() const;
+ /** Get the current char weight value for the whole shape.
+
+ @returns the value for the char weight. The value must
+ be out of the ::com::sun::star::awt::FontWeight
+ constant group.
+ */
+ double getCharWeight() const;
+ /** Set the char weight globally for the whole shape.
+
+ The value must be out of the
+ ::com::sun::star::awt::FontWeight constant group.
+ */
+ void setCharWeight( const double& rStyle );
+
+ /** Query whether the underline mode attribute is valid
+ */
+ bool isUnderlineModeValid() const;
+ /** Get the current text underline status for the whole shape.
+
+ If there is no unique underline status, false is returned.
+
+ @returns true for underlined text, false for normal.
+ */
+ sal_Int16 getUnderlineMode() const;
+ /** Set the underline status globally for the whole shape
+ */
+ void setUnderlineMode( const sal_Int16& bUnderline );
+
+ /** Query whether the font family attribute is valid
+ */
+ bool isFontFamilyValid() const;
+ /** Get the current text font family for the whole shape.
+
+ If there is no unique font family, the font family of
+ the first text of the shape is returned.
+ */
+ ::rtl::OUString getFontFamily() const;
+ /** Set the text font family name globally for the whole shape
+ */
+ void setFontFamily( const ::rtl::OUString& rName );
+
+ /** Query whether the italic mode attribute is valid
+ */
+ bool isCharPostureValid() const;
+ /** Get the current text italic style for the whole shape.
+
+ @returns the italic style. The value returned is one
+ of the ::com::sun::star::awt::FontSlant enums
+ */
+ sal_Int16 getCharPosture() const;
+ /** Set the italic style globally for the whole shape.
+
+ The value must be one of the
+ ::com::sun::star::awt::FontSlant enums.
+ */
+ void setCharPosture( const sal_Int16& rStyle );
+
+ /** Query whether the char scaling attribute is valid
+ */
+ bool isCharScaleValid() const;
+ /** Query the current char scaling attribute globally for
+ the shape.
+
+ The char scaling changes the scale of the whole shape
+ text (uniformely, i.e. both in x and in y direction).
+ */
+ double getCharScale() const;
+ /** Set the new char scale globally for the shape
+
+ @param rNewScale
+ New char scale
+ */
+ void setCharScale( const double& rNewScale );
+
+ // State change query methods
+ // ==========================
+
+ State::StateId getTransformationState() const;
+ State::StateId getClipState() const;
+ State::StateId getAlphaState() const;
+ State::StateId getPositionState() const;
+ State::StateId getContentState() const;
+ State::StateId getVisibilityState() const;
+
+ private:
+ // default copy/assignment operator is okay
+ // ShapeAttributeLayer(const ShapeAttributeLayer&);
+ // ShapeAttributeLayer& operator=( const ShapeAttributeLayer& );
+
+ bool haveChild() const { return mpChild; }
+ void updateStateIds();
+
+ template< typename T > T calcValue( const T& rCurrValue,
+ bool bThisInstanceValid,
+ bool (ShapeAttributeLayer::*pIsValid)() const,
+ T (ShapeAttributeLayer::*pGetValue)() const ) const;
+
+ ShapeAttributeLayerSharedPtr mpChild; // may be NULL
+
+ ::basegfx::B2DSize maSize;
+ ::basegfx::B2DPoint maPosition;
+ ::basegfx::B2DPolyPolygon maClip;
+
+ ::rtl::OUString maFontFamily;
+
+ double mnRotationAngle;
+ double mnShearXAngle;
+ double mnShearYAngle;
+ double mnAlpha;
+ double mnCharRotationAngle;
+ double mnCharScale;
+ double mnCharWeight;
+
+ ::com::sun::star::drawing::FillStyle meFillStyle;
+ ::com::sun::star::drawing::LineStyle meLineStyle;
+ ::com::sun::star::awt::FontSlant meCharPosture;
+ sal_Int16 mnUnderlineMode;
+
+ RGBColor maDimColor;
+ RGBColor maFillColor;
+ RGBColor maLineColor;
+ RGBColor maCharColor;
+
+ State::StateId mnTransformationState;
+ State::StateId mnClipState;
+ State::StateId mnAlphaState;
+ State::StateId mnPositionState;
+ State::StateId mnContentState;
+ State::StateId mnVisibilityState;
+
+ sal_Int16 mnAdditiveMode;
+
+ bool mbVisibility : 1;
+
+ bool mbWidthValid : 1;
+ bool mbHeightValid : 1;
+ bool mbPosXValid : 1;
+ bool mbPosYValid : 1;
+ bool mbClipValid : 1;
+
+ bool mbFontFamilyValid : 1;
+
+ bool mbRotationAngleValid : 1;
+ bool mbShearXAngleValid : 1;
+ bool mbShearYAngleValid : 1;
+
+ bool mbAlphaValid : 1;
+
+ bool mbCharRotationAngleValid: 1;
+ bool mbCharScaleValid : 1;
+
+ bool mbDimColorValid : 1;
+ bool mbFillColorValid : 1;
+ bool mbLineColorValid : 1;
+ bool mbCharColorValid : 1;
+
+ bool mbFillStyleValid : 1;
+ bool mbLineStyleValid : 1;
+ bool mbCharWeightValid : 1;
+ bool mbUnderlineModeValid : 1;
+ bool mbCharPostureValid : 1;
+ bool mbVisibilityValid : 1;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPEATTRIBUTELAYER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapeattributelayerholder.hxx b/slideshow/source/inc/shapeattributelayerholder.hxx
new file mode 100644
index 000000000000..989e306bd3b5
--- /dev/null
+++ b/slideshow/source/inc/shapeattributelayerholder.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPEATTRIBUTELAYERHOLDER_HXX
+#define INCLUDED_SLIDESHOW_SHAPEATTRIBUTELAYERHOLDER_HXX
+
+#include "attributableshape.hxx"
+#include "shapeattributelayer.hxx"
+
+#include <boost/noncopyable.hpp>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Holds a ShapeAttributeLayer, together with the associated
+ Shape
+
+ Use this class to hold ShapeAttributeLayer objects the
+ RAII way. When this object gets deleted, it will
+ automatically revoke the attribute layer for the given
+ shape (this encapsulates the somewhat clumsy notification
+ process that is required for shape and attribute layer
+ interaction).
+ */
+ class ShapeAttributeLayerHolder : private boost::noncopyable
+ {
+ public:
+ /** Create a ShapeAttributeLayerHolder instance.
+
+ This constructor creates an empty attribute holder, to
+ generate an attribute layer, you have to manually call
+ createAttributeLayer().
+ */
+ ShapeAttributeLayerHolder() :
+ mpShape(),
+ mpAttributeLayer()
+ {
+ }
+
+ ~ShapeAttributeLayerHolder()
+ {
+ reset(); // ensures that the last attribute layer is
+ // correctly deregistered from the shape.
+ }
+
+ void reset()
+ {
+ if( mpShape && mpAttributeLayer )
+ mpShape->revokeAttributeLayer( mpAttributeLayer );
+ }
+
+ /** This constructor receives a pointer to the Shape, from
+ which attribute layers should be generated. Initially,
+ this object does not create an attribute layer, you
+ have to manually call createAttributeLayer().
+
+ @param rShape
+ Shape for which attribute layers should be generated.
+ */
+ bool createAttributeLayer( const AttributableShapeSharedPtr& rShape )
+ {
+ reset();
+
+ mpShape = rShape;
+
+ if( mpShape )
+ mpAttributeLayer = mpShape->createAttributeLayer();
+
+ return mpAttributeLayer;
+ }
+
+ ShapeAttributeLayerSharedPtr get() const
+ {
+ return mpAttributeLayer;
+ }
+
+ private:
+ AttributableShapeSharedPtr mpShape;
+ ShapeAttributeLayerSharedPtr mpAttributeLayer;
+ };
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPEATTRIBUTELAYERHOLDER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapecursoreventhandler.hxx b/slideshow/source/inc/shapecursoreventhandler.hxx
new file mode 100644
index 000000000000..298ce67e1da2
--- /dev/null
+++ b/slideshow/source/inc/shapecursoreventhandler.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPECURSOREVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_SHAPECURSOREVENTHANDLER_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ class XShape;
+} } } }
+
+/* Definition of ShapeCursorEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling view events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle view events.
+ */
+ class ShapeCursorEventHandler
+ {
+ public:
+ virtual ~ShapeCursorEventHandler() {}
+
+ virtual bool cursorChanged( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape,
+ sal_Int16 nCursor ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ShapeCursorEventHandler > ShapeCursorEventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPECURSOREVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapeimporter.hxx b/slideshow/source/inc/shapeimporter.hxx
new file mode 100644
index 000000000000..0e7023b5cbc3
--- /dev/null
+++ b/slideshow/source/inc/shapeimporter.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_SHAPEIMPORTER_HXX
+#define INCLUDED_SLIDESHOW_SHAPEIMPORTER_HXX
+
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XLayer.hpp>
+#include "unoviewcontainer.hxx"
+#include "unoview.hxx"
+
+#include "shape.hxx"
+
+#include <stack>
+
+namespace slideshow {
+namespace internal {
+
+struct SlideShowContext;
+
+typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
+typedef ::boost::shared_ptr< UnoView > UnoViewSharedPtr;
+typedef ::std::vector< UnoViewSharedPtr > UnoViewVector;
+
+/** This class imports all shapes from a given XShapes object
+ */
+class ShapeImporter
+{
+public:
+ /** Create shape importer.
+
+ @param xPage
+ Page containing the shapes
+
+ @param xActualPage
+ Actual page that's imported - if xPage is a master
+ page, this argument must refer to the using, i.e the
+ page that embeds this specific masterpage. Otherwise,
+ this argument is probably equal to xPage.
+
+ @param nOrdNumStart
+ Each shape receives a z order number, in order of
+ import (which relies on the fact that the API returns
+ the shapes in draw order - which it does,
+ currently). Since we might mix several pages on screen
+ (e.g. master page and foreground page), this value can
+ be used as an offset to distinguish those pages.
+
+ @param bConvertingMasterPage
+ When true, then the master page is imported. Otherwise, this
+ object imports the draw page.
+ */
+ ShapeImporter( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xPage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xActualPage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPagesSupplier>& xPagesSupplier,
+ const SlideShowContext& rContext,
+ sal_Int32 nOrdNumStart,
+ bool bConvertingMasterPage );
+
+ /** This method imports the presentation background shape
+ */
+ ShapeSharedPtr importBackgroundShape(); // throw (ShapeLoadFailedException)
+
+ /** This method imports presentation-visible shapes (and skips all others).
+
+ @return the generated Shape, or NULL for no more shapes.
+ */
+ ShapeSharedPtr importShape(); // throw (ConversionFailedException)
+
+ /** Test whether import is done.
+
+ @return true, if all shapes are imported via the
+ importShape() call.
+ */
+ bool isImportDone() const;
+ PolyPolygonVector getPolygons();
+private:
+ bool isSkip( ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet> const& xPropSet,
+ ::rtl::OUString const& shapeType,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XLayer> const& xLayer);
+
+ ShapeSharedPtr createShape(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape> const& xCurrShape,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::beans::XPropertySet> const& xPropSet,
+ ::rtl::OUString const& shapeType ) const;
+
+ void importPolygons(::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > const& xPropSet) ;
+
+ struct XShapesEntry
+ {
+ ShapeSharedPtr const mpGroupShape;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes> const mxShapes;
+ sal_Int32 const mnCount;
+ sal_Int32 mnPos;
+
+ explicit XShapesEntry( ShapeSharedPtr const& pGroupShape )
+ : mpGroupShape(pGroupShape),
+ mxShapes( pGroupShape->getXShape(),
+ ::com::sun::star::uno::UNO_QUERY_THROW ),
+ mnCount(mxShapes->getCount()), mnPos(0) {}
+ explicit XShapesEntry( ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShapes> const& xShapes )
+ : mpGroupShape(), mxShapes(xShapes),
+ mnCount(xShapes->getCount()), mnPos(0) {}
+ };
+ typedef ::std::stack<XShapesEntry> XShapesStack;
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage> mxPage;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPagesSupplier> mxPagesSupplier;
+ const SlideShowContext& mrContext;
+ PolyPolygonVector maPolygons;
+ XShapesStack maShapesStack;
+ double mnAscendingPrio;
+ bool mbConvertingMasterPage;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapelistenereventhandler.hxx b/slideshow/source/inc/shapelistenereventhandler.hxx
new file mode 100644
index 000000000000..df8b63f80a87
--- /dev/null
+++ b/slideshow/source/inc/shapelistenereventhandler.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPELISTENEREVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_SHAPELISTENEREVENTHANDLER_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ class XShape;
+} namespace presentation {
+ class XShapeEventListener;
+} } } }
+
+/* Definition of ShapeListenerEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling view events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle view events.
+ */
+ class ShapeListenerEventHandler
+ {
+ public:
+ virtual ~ShapeListenerEventHandler() {}
+
+ virtual bool listenerAdded( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XShapeEventListener>& xListener,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape ) = 0;
+
+ virtual bool listenerRemoved( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XShapeEventListener>& xListener,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>& xShape ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ShapeListenerEventHandler > ShapeListenerEventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPELISTENEREVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapemanager.hxx b/slideshow/source/inc/shapemanager.hxx
new file mode 100644
index 000000000000..b6790460095f
--- /dev/null
+++ b/slideshow/source/inc/shapemanager.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPEMANAGER_HXX
+#define INCLUDED_SLIDESHOW_SHAPEMANAGER_HXX
+
+#include "disposable.hxx"
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star { namespace drawing {
+ class XShape;
+} } } }
+
+/* Definition of ShapeManager interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class HyperlinkArea;
+ class AnimatableShape;
+ class Shape;
+
+ /** ShapeManager interface
+
+ Implementers of this interface manage appearance and
+ animation of slideshow shapes.
+ */
+ class ShapeManager : public Disposable
+ {
+ public:
+ /** Notify the ShapeManager that the given Shape starts an
+ animation now.
+
+ This method enters animation mode for the Shape. If
+ the shape is already in animation mode, the call is
+ counted, and the shape only leaves animation mode
+ after a corresponding number of leaveAnimationMode()
+ calls.
+ */
+ virtual void enterAnimationMode( const boost::shared_ptr<AnimatableShape>& rShape ) = 0;
+
+ /** Notify the ShapeManager that the given Shape is no
+ longer animated.
+
+ When called a corresponding number of times as
+ enterAnimationMode() for a given shape, this methods
+ ends animation mode for the given Shape. It is illegal
+ to call this method more often than
+ enterAnimationMode().
+ */
+ virtual void leaveAnimationMode( const boost::shared_ptr<AnimatableShape>& rShape ) = 0;
+
+ /** Notify that a shape needs an update
+
+ This method notifies the ShapeManager that a shape
+ update is necessary. Use this if e.g. a running
+ animation changed the shape appearance.
+
+ @param rShape
+ Shape which needs an update
+ */
+ virtual void notifyShapeUpdate( const boost::shared_ptr<Shape>& rShape ) = 0;
+
+ /** Lookup a Shape from an XShape model object
+
+ This method looks up the internal shape map for one
+ representing the given XShape.
+
+ @param xShape
+ The XShape object, for which the representing Shape
+ should be looked up.
+ */
+ virtual boost::shared_ptr<Shape> lookupShape(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape > const & xShape ) const = 0;
+
+ /** Register given shape as a hyperlink target
+
+ @param rArea
+ Hyperlink sensitive area. Will participate in
+ hyperlink region lookup. Must be in absolute user
+ space coordinates.
+ */
+ virtual void addHyperlinkArea( const boost::shared_ptr<HyperlinkArea>& rArea ) = 0;
+
+ /** Unregister given shape as a hyperlink target
+
+ @param rArea
+ Hyperlink sensitive area. Will cease to participate in
+ hyperlink region lookup.
+ */
+ virtual void removeHyperlinkArea( const boost::shared_ptr<HyperlinkArea>& rArea ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ShapeManager > ShapeManagerSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPEMANAGER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapemaps.hxx b/slideshow/source/inc/shapemaps.hxx
new file mode 100644
index 000000000000..a6987a46cfa5
--- /dev/null
+++ b/slideshow/source/inc/shapemaps.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPEMAPS_HXX
+#define INCLUDED_SLIDESHOW_SHAPEMAPS_HXX
+
+#include <cppuhelper/interfacecontainer.h>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <map>
+
+namespace com { namespace sun { namespace star { namespace drawing
+{
+ class XShape;
+} } } }
+
+/* Definition of two shape maps */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /// Maps XShape to shape listener
+ typedef ::std::map< ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>,
+ boost::shared_ptr< ::cppu::OInterfaceContainerHelper >
+ > ShapeEventListenerMap;
+
+ /// Maps XShape to mouse cursor
+ typedef ::std::map< ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape>,
+ sal_Int16> ShapeCursorMap;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPEMAPS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/shapesubset.hxx b/slideshow/source/inc/shapesubset.hxx
new file mode 100644
index 000000000000..2ae2196c1158
--- /dev/null
+++ b/slideshow/source/inc/shapesubset.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SHAPESUBSET_HXX
+#define INCLUDED_SLIDESHOW_SHAPESUBSET_HXX
+
+#include "attributableshape.hxx"
+#include "subsettableshapemanager.hxx"
+#include "doctreenode.hxx"
+
+#include <boost/shared_ptr.hpp>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class ShapeSubset;
+ typedef ::boost::shared_ptr< ShapeSubset > ShapeSubsetSharedPtr;
+
+ /* Definition of ShapeSubset class */
+
+ /** Subset RAII wrapper for shapes.
+
+ This class wraps the plain Shape with a wrapper for subset
+ functionality. Subsetting can be turned on and off. Note
+ that the reason to have shape subsetting RAII implemented
+ separately (i.e. not within the DrawShape) was that
+ subsetting (and de-subsetting) needs the
+ SubsettableShapeManager. And holding that at the DrawShape
+ creates one heck of a circular reference.
+ */
+ class ShapeSubset
+ {
+ public:
+ /** Create a subset directly from a Shape.
+
+ @param rOriginalShape
+ Original shape to subset
+
+ @param rTreeNode
+ Subset this object should represent
+
+ @param rShapeManager
+ Manager object, where subsets are
+ registered/unregistered
+ */
+ ShapeSubset( const AttributableShapeSharedPtr& rOriginalShape,
+ const DocTreeNode& rTreeNode,
+ const SubsettableShapeManagerSharedPtr& rSubsetManager );
+
+ /** Create a subset from another subset.
+
+ Note: if you want this subset to subtract from the
+ passed subset reference (and not from the original,
+ unsubsetted shape), the passed subset must be enabled
+ (enableSubsetShape() must have been called)
+
+ @param rOriginalSubset
+ Original subset, which to subset again.
+
+ @param rTreeNode
+ Subset of the original subset
+ */
+ ShapeSubset( const ShapeSubsetSharedPtr& rOriginalSubset,
+ const DocTreeNode& rTreeNode );
+
+ /** Create full set for the given shape.
+
+ @param rOriginalShape
+ Original shape, which will be represented as a whole
+ by this object
+ */
+ ShapeSubset( const AttributableShapeSharedPtr& rOriginalShape,
+ const SubsettableShapeManagerSharedPtr& rShapeManager );
+
+ ~ShapeSubset();
+
+ /** Get the actual subset shape.
+
+ If the subset is currently revoked, this method
+ returns the original shape.
+ */
+ AttributableShapeSharedPtr getSubsetShape() const;
+
+ /** Enable the subset shape.
+
+ This method enables the subset. That means, on
+ successful completion of this method, the original
+ shape will cease to show the subset range, and
+ getSubsetShape() will return a valid shape.
+
+ @return true, if subsetting was successfully enabled.
+ */
+ bool enableSubsetShape();
+
+ /** Disable the subset shape.
+
+ This method revokes the subset from the original
+ shape. That means, the original shape will again show
+ the hidden range.
+ */
+ void disableSubsetShape();
+
+ /** Query whether this subset actually is none, but
+ contains the whole original shape's content
+ */
+ bool isFullSet() const;
+
+ /** Query subset this object represents
+ */
+ DocTreeNode getSubset() const;
+
+ private:
+ // default copy/assignment are okay
+ //ShapeSubset(const ShapeSubset&);
+ //ShapeSubset& operator=( const ShapeSubset& );
+
+ AttributableShapeSharedPtr mpOriginalShape;
+ AttributableShapeSharedPtr mpSubsetShape;
+ DocTreeNode maTreeNode;
+ SubsettableShapeManagerSharedPtr mpShapeManager;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SHAPESUBSET_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/slide.hxx b/slideshow/source/inc/slide.hxx
new file mode 100644
index 000000000000..7d6e0a17da25
--- /dev/null
+++ b/slideshow/source/inc/slide.hxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SLIDE_HXX
+#define INCLUDED_SLIDESHOW_SLIDE_HXX
+
+#include "shapemanager.hxx"
+#include "subsettableshapemanager.hxx"
+#include "unoviewcontainer.hxx"
+#include "slidebitmap.hxx"
+#include "shapemaps.hxx"
+
+#include <boost/shared_ptr.hpp>
+
+namespace com { namespace sun { namespace star {
+ namespace drawing {
+ class XDrawPage;
+ class XDrawPagesSupplier;
+ }
+ namespace uno {
+ class XComponentContext;
+ }
+ namespace animations {
+ class XAnimationNode;
+} } } }
+
+namespace basegfx
+{
+ class B2IVector;
+}
+
+/* Definition of Slide interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class RGBColor;
+ class ScreenUpdater;
+ typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
+ class Slide
+ {
+ public:
+ // Showing
+ // -------------------------------------------------------------------
+
+ /** Prepares to show slide.
+
+ Call this method to reduce the timeout show(), and
+ getInitialSlideBitmap() need to complete. If
+ prefetch() is not called explicitely, the named
+ methods will call it implicitely.
+ */
+ virtual bool prefetch() = 0;
+
+ /** Shows the slide on all registered views
+
+ After this call, the slide will render itself to the
+ views, and start its animations.
+
+ @param bSlideBackgoundPainted
+ When true, the initial slide content on the background
+ layer is already rendered (e.g. from a previous slide
+ transition). When false, Slide renders initial content of
+ slide.
+ */
+ virtual bool show( bool bSlideBackgoundPainted ) = 0;
+
+ /** Force-ends the slide
+
+ After this call, the slide has stopped all animations,
+ and ceased rendering/visualization on all views.
+ */
+ virtual void hide() = 0;
+
+
+ // Queries
+ // -------------------------------------------------------------------
+
+ /** Query the size of this slide in user coordinates
+
+ This value is retrieved from the XDrawPage properties.
+ */
+ virtual basegfx::B2IVector getSlideSize() const = 0;
+
+ /// Gets the underlying API page
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage > getXDrawPage() const = 0;
+
+ /// Gets the animation node.
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode > getXAnimationNode() const = 0;
+
+ ///Gets the slide Polygons
+ virtual PolyPolygonVector getPolygons() = 0;
+
+ ///Draw the slide Polygons
+ virtual void drawPolygons() const = 0;
+
+ ///Check if slide is already active
+ virtual bool isPaintOverlayActive() const = 0;
+
+ // Slide bitmaps
+ // -------------------------------------------------------------------
+
+ /** Request bitmap for current slide appearance.
+
+ The bitmap returned by this method depends on the
+ current state of the slide and the contained
+ animations. A newly generated slide will return the
+ initial slide content here (e.g. with all 'appear'
+ effect shapes invisible), a slide whose effects are
+ currently running will return a bitmap corresponding
+ to the current position on the animation timeline, and
+ a slide whose effects have all been run will generate
+ a bitmap with the final slide appearance (e.g. with
+ all 'hide' effect shapes invisible).
+
+ @param rView
+ View to retrieve bitmap for (note that the bitmap will
+ have device-pixel equivalence to the content that
+ would have been rendered onto the given view). Note
+ that the view must have been added to this slide
+ before via viewAdded().
+ */
+ virtual SlideBitmapSharedPtr
+ getCurrentSlideBitmap( const UnoViewSharedPtr& rView ) const = 0;
+ };
+
+ typedef ::boost::shared_ptr< Slide > SlideSharedPtr;
+
+ class EventQueue;
+ class CursorManager;
+ class EventMultiplexer;
+ class ActivitiesQueue;
+ class UserEventQueue;
+ class RGBColor;
+
+ /** Construct from XDrawPage
+
+ The Slide object generally works in XDrawPage model
+ coordinates, that is, the page will have the width and
+ height as specified in the XDrawPage's property
+ set. The top, left corner of the page will be rendered
+ at (0,0) in the given canvas' view coordinate system.
+
+ Does not render anything initially
+
+ @param xDrawPage
+ Page to display on this slide
+
+ @param xRootNode
+ Root of the SMIL animation tree. Used to animate the slide.
+
+ @param rEventQueue
+ EventQueue. Used to post events.
+
+ @param rActivitiesQueue
+ ActivitiesQueue. Used to run animations.
+
+ @param rEventMultiplexer
+ Event source
+
+ @param rUserEventQueue
+ UserEeventQueue
+ */
+ SlideSharedPtr createSlide( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPage >& xDrawPage,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XDrawPagesSupplier >& xDrawPages,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode >& xRootNode,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext >& xContext,
+ const ShapeEventListenerMap& rShapeListenerMap,
+ const ShapeCursorMap& rShapeCursorMap,
+ const PolyPolygonVector& rPolyPolygonVector,
+ RGBColor const& aUserPaintColor,
+ double dUserPaintStrokeWidth,
+ bool bUserPaintEnabled,
+ bool bIntrinsicAnimationsAllowed,
+ bool bDisableAnimationZOrder );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SLIDE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/slidebitmap.hxx b/slideshow/source/inc/slidebitmap.hxx
new file mode 100644
index 000000000000..5f7f5e4d693a
--- /dev/null
+++ b/slideshow/source/inc/slidebitmap.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SLIDEBITMAP_HXX
+#define INCLUDED_SLIDESHOW_SLIDEBITMAP_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <cppcanvas/canvas.hxx>
+#include <cppcanvas/bitmap.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace com { namespace sun { namespace star { namespace rendering
+{
+ class XBitmap;
+} } } }
+
+
+/* Definition of SlideBitmap class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Little wrapper encapsulating an XBitmap
+
+ This is to insulate us from changes to the preferred
+ transport format for bitmaps (using a sole XBitmap here is
+ a hack, since it is not guaranteed to work, or to work
+ without data loss, across different canvases). And since
+ we don't want to revert to a VCL Bitmap here, have to wait
+ until basegfx bitmap tooling is ready.
+
+ TODO(F2): Add support for Canvas-independent bitmaps
+ here. Then, Slide::getInitialSlideBitmap and
+ Slide::getFinalSlideBitmap must also be adapted (they no
+ longer need a Canvas ptr, which is actually a hack now).
+ */
+ class SlideBitmap : private boost::noncopyable
+ {
+ public:
+ SlideBitmap( const ::cppcanvas::BitmapSharedPtr& rBitmap );
+
+ bool draw( const ::cppcanvas::CanvasSharedPtr& rCanvas ) const;
+ ::basegfx::B2ISize getSize() const;
+ ::basegfx::B2DPoint getOutputPos() const{return maOutputPos;}
+ void move( const ::basegfx::B2DPoint& rNewPos );
+ void clip( const ::basegfx::B2DPolyPolygon& rClipPoly );
+
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > getXBitmap();
+
+ private:
+ ::basegfx::B2DPoint maOutputPos;
+ ::basegfx::B2DPolyPolygon maClipPoly;
+
+ // TODO(Q2): Remove UNO bitmap as the transport medium
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::rendering::XBitmap > mxBitmap;
+ };
+
+ typedef ::boost::shared_ptr< SlideBitmap > SlideBitmapSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SLIDEBITMAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/slideshowcontext.hxx b/slideshow/source/inc/slideshowcontext.hxx
new file mode 100644
index 000000000000..72681993d862
--- /dev/null
+++ b/slideshow/source/inc/slideshowcontext.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SLIDESHOWCONTEXT_HXX
+#define INCLUDED_SLIDESHOW_SLIDESHOWCONTEXT_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <boost/shared_ptr.hpp>
+
+namespace com{ namespace sun{ namespace star{ namespace uno
+{
+ class XComponentContext;
+}}}}
+
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class ShapeManager;
+ class EventQueue;
+ class ActivitiesQueue;
+ class UserEventQueue;
+ class EventMultiplexer;
+ class ScreenUpdater;
+ class UnoViewContainer;
+ class CursorManager;
+ class SubsettableShapeManager;
+
+ /** Common arguments for slideshow objects.
+
+ This struct combines a number of object references
+ ubiquituously needed throughout the slideshow.
+ */
+ struct SlideShowContext
+ {
+ /** Common context for node creation
+
+ @param rShapeManager
+ ShapeManager, which handles all shapes
+
+ @param rEventQueue
+ Event queue, where time-based events are to be
+ scheduled. A node must not schedule events there
+ before it's not resolved.
+
+ @param rEventMultiplexer
+ Event multiplexer. Clients can register there for
+ about any event that happens in the slideshow
+
+ @param rScreenUpdater
+ Screen updater. Gets notified of necessary screen
+ updates.
+
+ @param rActivitiesQueue
+ Activities queue, where repeating activities are
+ to be scheduled.
+
+ @param rUserEventQueue
+ User event queue
+
+ @param rViewContainer
+ Holds all views added to slideshow
+
+ @param rComponentContext
+ To create UNO services from
+ */
+ SlideShowContext( boost::shared_ptr<SubsettableShapeManager>& rSubsettableShapeManager,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer,
+ ScreenUpdater& rScreenUpdater,
+ ActivitiesQueue& rActivitiesQueue,
+ UserEventQueue& rUserEventQueue,
+ CursorManager& rCursorManager,
+ const UnoViewContainer& rViewContainer,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext>& rComponentContext );
+ void dispose();
+
+ boost::shared_ptr<SubsettableShapeManager>& mpSubsettableShapeManager;
+ EventQueue& mrEventQueue;
+ EventMultiplexer& mrEventMultiplexer;
+ ScreenUpdater& mrScreenUpdater;
+ ActivitiesQueue& mrActivitiesQueue;
+ UserEventQueue& mrUserEventQueue;
+ CursorManager& mrCursorManager;
+ const UnoViewContainer& mrViewContainer;
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext> mxComponentContext;
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SLIDESHOWCONTEXT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/slideshowexceptions.hxx b/slideshow/source/inc/slideshowexceptions.hxx
new file mode 100644
index 000000000000..f0e1656f39a0
--- /dev/null
+++ b/slideshow/source/inc/slideshowexceptions.hxx
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SLIDESHOWEXCEPTIONS_HXX
+#define INCLUDED_SLIDESHOW_SLIDESHOWEXCEPTIONS_HXX
+
+
+namespace slideshow
+{
+ class SlideShowException {};
+
+ /** This exception is thrown, when the Shape class was not
+ able to convert an API object into our internal
+ representation.
+ */
+ struct ShapeLoadFailedException : public SlideShowException {};
+
+ /** This exception is thrown, when the SMIL arithmetic expression
+ parser failed to parse a string.
+ */
+ struct ParseError : public SlideShowException
+ {
+ ParseError() {}
+ explicit ParseError( const char* ) {}
+ };
+
+}
+
+#endif /* INCLUDED_SLIDESHOW_SLIDESHOWEXCEPTIONS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/slideview.hxx b/slideshow/source/inc/slideview.hxx
new file mode 100644
index 000000000000..f791f15a132a
--- /dev/null
+++ b/slideshow/source/inc/slideview.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SLIDEVIEW_HXX
+#define INCLUDED_SLIDESHOW_SLIDEVIEW_HXX
+
+#include "unoview.hxx"
+
+/* Definition of SlideView factory method */
+namespace slideshow
+{
+ namespace internal
+ {
+ class EventQueue;
+ class EventMultiplexer;
+
+ /** Factory for SlideView
+
+ @param xView
+ UNO slide view this object should encapsulate
+
+ @param rEventQueue
+ Global event queue, to be used for notification
+ messages.
+
+ @param rViewChangeFunc
+ Functor to call, when the UNO view signals a repaint.
+ */
+ UnoViewSharedPtr createSlideView(
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XSlideShowView> const& xView,
+ EventQueue& rEventQueue,
+ EventMultiplexer& rEventMultiplexer );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SLIDEVIEW_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/smilfunctionparser.hxx b/slideshow/source/inc/smilfunctionparser.hxx
new file mode 100644
index 000000000000..c99550ec6656
--- /dev/null
+++ b/slideshow/source/inc/smilfunctionparser.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SMILFUNCTIONPARSER_HXX
+#define INCLUDED_SLIDESHOW_SMILFUNCTIONPARSER_HXX
+
+#include "expressionnode.hxx"
+#include "slideshowexceptions.hxx"
+
+#include <basegfx/range/b2drectangle.hxx>
+
+#include <boost/noncopyable.hpp>
+
+namespace rtl
+{
+ class OUString;
+}
+
+/* Definition of SmilFunctionParser class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class SmilFunctionParser : private boost::noncopyable
+ {
+ public:
+ /** Parse a string containing a SMIL value.
+
+ This method parses a string representing
+ a fixed value (i.e. a value that does not
+ change by time). Due to the dynamic view
+ capabilities of the presentation engine,
+ this value can sometimes only be determined
+ during runtime of the animation (because
+ e.g. mixed screen/view coordinates are
+ involved), and is thus still returned as an
+ ExpressionNode object. An example for
+ such a case is the "Width+1.0" string, which
+ contains the width of the shape in user
+ coordinate space, and the screen width
+ in device coordinate space.
+
+ The following grammar is accepted by this method:
+ <code>
+ identifier = 'pi'|'e'|'X'|'Y'|'Width'|'Height'
+
+ function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
+
+ basic_expression =
+ number |
+ identifier |
+ function '(' additive_expression ')' |
+ '(' additive_expression ')'
+
+ unary_expression =
+ '-' basic_expression |
+ basic_expression
+
+ multiplicative_expression =
+ unary_expression ( ( '*' unary_expression )* |
+ ( '/' unary_expression )* )
+
+ additive_expression =
+ multiplicative_expression ( ( '+' multiplicative_expression )* |
+ ( '-' multiplicative_expression )* )
+
+ </code>
+
+ @param rSmilValue
+ The string to parse
+
+ @param rRelativeShapeBounds
+ The bounds of the shape this SMIL value is to be
+ evaluated for. The bounds must be <em>relative</em> to
+ the page the shape is part of, i.e. within the [0,1]
+ range. This is necessary, since the string might
+ contain symbolic references to the shape bounding box.
+
+ @throws ParseError if an invalid expression is given.
+
+ @return the generated function object.
+ */
+ static ExpressionNodeSharedPtr parseSmilValue( const ::rtl::OUString& rSmilValue,
+ const ::basegfx::B2DRectangle& rRelativeShapeBounds ); // throw ParseError
+
+ /** Parse a string containing a SMIL function.
+
+ This method parses a string representing
+ a possibly time-varying SMIL function.
+
+ The following grammar is accepted by this method:
+ <code>
+ identifier = 't'|'pi'|'e'|'X'|'Y'|'Width'|'Height'
+
+ function = 'abs'|'sqrt'|'sin'|'cos'|'tan'|'atan'|'acos'|'asin'|'exp'|'log'
+
+ basic_expression =
+ number |
+ identifier |
+ function '(' additive_expression ')' |
+ '(' additive_expression ')'
+
+ unary_expression =
+ '-' basic_expression |
+ basic_expression
+
+ multiplicative_expression =
+ unary_expression ( ( '*' unary_expression )* |
+ ( '/' unary_expression )* )
+
+ additive_expression =
+ multiplicative_expression ( ( '+' multiplicative_expression )* |
+ ( '-' multiplicative_expression )* )
+
+ </code>
+
+ @param rSmilFunction
+ The string to parse
+
+ @param rRelativeShapeBounds
+ The bounds of the shape this SMIL value is to be
+ evaluated for. The bounds must be <em>relative</em> to
+ the page the shape is part of, i.e. within the [0,1]
+ range. This is necessary, since the string might
+ contain symbolic references to the shape bounding box.
+
+ @throws ParseError if an invalid expression is given.
+
+ @return the generated function object.
+ */
+ static ExpressionNodeSharedPtr parseSmilFunction( const ::rtl::OUString& rSmilFunction,
+ const ::basegfx::B2DRectangle& rRelativeShapeBounds ); // throw ParseError
+
+ private:
+ // disabled constructor/destructor, since this is
+ // supposed to be a singleton
+ SmilFunctionParser();
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SMILFUNCTIONPARSER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/soundplayer.hxx b/slideshow/source/inc/soundplayer.hxx
new file mode 100644
index 000000000000..edebe5f97905
--- /dev/null
+++ b/slideshow/source/inc/soundplayer.hxx
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX
+#define INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX
+
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/media/XManager.hpp>
+#include <com/sun/star/media/XPlayer.hpp>
+
+#include <boost/shared_ptr.hpp>
+
+#include "pauseeventhandler.hxx"
+#include "disposable.hxx"
+#include "eventmultiplexer.hxx"
+
+
+/* Definition of SoundPlayer class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Little class that plays a sound from a URL.
+ TODO:
+ Must be explicitly disposed (as long as enable_shared_ptr_from_this
+ isn't available)!
+ */
+ class SoundPlayer : public PauseEventHandler,
+ public Disposable
+ {
+ public:
+ /** Create a sound player object.
+
+ @param rSoundURL
+ URL to a sound file.
+
+ @param rComponentContext
+ Reference to a component context, used to create the
+ needed services
+
+ @throws ::com::sun::star::lang::NoSupportException, if
+ the sound file is invalid, or not supported by the
+ player service.
+ */
+ static ::boost::shared_ptr<SoundPlayer> create(
+ EventMultiplexer & rEventMultiplexer,
+ const ::rtl::OUString& rSoundURL,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext>& rComponentContext );
+
+ virtual ~SoundPlayer();
+
+ /** Query duration of sound playback.
+
+ If the sound is already playing, this method
+ returns the remaining playback time.
+
+ @return the playback duration in seconds.
+ */
+ double getDuration() const;
+
+ bool startPlayback();
+ bool stopPlayback();
+
+ void setPlaybackLoop( bool bLoop );
+
+ // PauseEventHandler:
+ virtual bool handlePause( bool bPauseShow );
+
+ // Disposable
+ virtual void dispose();
+
+ private:
+ SoundPlayer(
+ EventMultiplexer & rEventMultiplexer,
+ const ::rtl::OUString& rSoundURL,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XComponentContext>& rComponentContext );
+
+ EventMultiplexer & mrEventMultiplexer;
+ // TODO(Q3): obsolete when boost::enable_shared_ptr_from_this
+ // is available
+ ::boost::shared_ptr<SoundPlayer> mThis;
+ ::com::sun::star::uno::Reference< ::com::sun::star::media::XPlayer > mxPlayer;
+ };
+
+ typedef ::boost::shared_ptr< SoundPlayer > SoundPlayerSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SOUNDPLAYER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/state.hxx b/slideshow/source/inc/state.hxx
new file mode 100644
index 000000000000..d48f7a492c70
--- /dev/null
+++ b/slideshow/source/inc/state.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_STATE_HXX
+#define INCLUDED_SLIDESHOW_STATE_HXX
+
+#include <sal/types.h>
+#include <boost/shared_ptr.hpp>
+
+
+/* Definition of State interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** This interface represents a stateful object.
+
+ The state ID returned by the getStateId() method
+ abstractly encodes the object's state. When this ID
+ changes, clients can assume that the object's state has
+ changed.
+ */
+ class State
+ {
+ public:
+ virtual ~State() {}
+
+ /// Abstract, numerically encoded state ID
+ typedef ::std::size_t StateId;
+
+ /** This method returns a numerical state identifier.
+
+ The state ID returned by this method abstractly
+ encodes the object's state. When this ID changes,
+ clients can assume that the object's state has
+ changed.
+
+ @return an abstract, numerical state ID.
+ */
+ virtual StateId getStateId() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< State > StateSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_STATE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/stringanimation.hxx b/slideshow/source/inc/stringanimation.hxx
new file mode 100644
index 000000000000..4b3457deb6bd
--- /dev/null
+++ b/slideshow/source/inc/stringanimation.hxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_STRINGANIMATION_HXX
+#define INCLUDED_SLIDESHOW_STRINGANIMATION_HXX
+
+#include "animation.hxx"
+#include <rtl/ustring.hxx>
+
+
+/* Definition of StringAnimation interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface defining a string animation.
+
+ This interface is a specialization of the Animation
+ interface, and is used to animate attributes representable
+ by a discrete character string (e.g. font names)
+ */
+ class StringAnimation : public Animation
+ {
+ public:
+ typedef ::rtl::OUString ValueType;
+
+ /** Set the animation to value rStr
+
+ @param rStr
+ Current animation value.
+ */
+ virtual bool operator()( const ValueType& rStr ) = 0;
+
+ /** Request the underlying value for this animation.
+
+ This is necessary for pure To or By animations, as the
+ Activity cannot determine a sensible start value
+ otherwise.
+
+ @attention Note that you are only permitted to query
+ for the underlying value, if the animation has actually
+ been started (via start() call).
+ */
+ virtual ValueType getUnderlyingValue() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< StringAnimation > StringAnimationSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_STRINGANIMATION_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/subsettableshapemanager.hxx b/slideshow/source/inc/subsettableshapemanager.hxx
new file mode 100644
index 000000000000..b4b4a8819f32
--- /dev/null
+++ b/slideshow/source/inc/subsettableshapemanager.hxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_SUBSETTABLESHAPEMANAGER_HXX
+#define INCLUDED_SLIDESHOW_SUBSETTABLESHAPEMANAGER_HXX
+
+#include "shapemanager.hxx"
+#include "intrinsicanimationeventhandler.hxx"
+#include <boost/shared_ptr.hpp>
+
+/* Definition of SubsettableShapeManager interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class DocTreeNode;
+ class AttributableShape;
+
+ /** SubsettableShapeManager interface
+
+ Implementers of this interface manage creation and
+ revocation of shape subsets. Shape subsets are shapes that
+ represent (and animate) only parts of an original's shape
+ content.
+ */
+ class SubsettableShapeManager : public ShapeManager
+ {
+ public:
+ /** Query a subset of the given original shape
+
+ This method queries a new (but not necessarily unique)
+ shape, which displays only the given subset of the
+ original one. Calling this method multiple times with
+ the same original shape and DocTreeNode content always
+ returns the same shape.
+
+ Requesting a subset from an original shape leads to
+ the original shape ceasing to display the subsetted
+ content. In other words, shape content is always
+ displayed in exactly one shape.
+
+ @param rOrigShape
+ The shape the subset is to be created for
+
+ @param rSubsetShape
+ The subset to display in the generated shape.
+ */
+ virtual boost::shared_ptr<AttributableShape> getSubsetShape(
+ const boost::shared_ptr<AttributableShape>& rOrigShape,
+ const DocTreeNode& rTreeNode ) = 0;
+
+ /** Revoke a previously queried subset shape.
+
+ With this method, a previously requested subset shape
+ is revoked again. If the last client revokes a given
+ subset, it will cease to be displayed, and the
+ original shape will again show the subset data.
+
+ @param rOrigShape
+ The shape the subset was created from
+
+ @param rSubsetShape
+ The subset created from rOrigShape
+ */
+ virtual void revokeSubset(
+ const boost::shared_ptr<AttributableShape>& rOrigShape,
+ const boost::shared_ptr<AttributableShape>& rSubsetShape ) = 0;
+
+ // Evil hackish way of getting intrinsic animation slide-wise
+
+ /** Register an event handler that will be called when
+ user paint parameters change.
+
+ @param rHandler
+ Handler to call when a shape listener changes
+ */
+ virtual void addIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler ) = 0;
+ virtual void removeIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler ) = 0;
+
+ /** Notify that shape-intrinsic animations are now enabled.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ virtual bool notifyIntrinsicAnimationsEnabled() = 0;
+
+ /** Notify that shape-intrinsic animations are now disabled.
+
+ @return true, if this event was processed by
+ anybody. If false is returned, no handler processed
+ this event (and probably, nothing will happen at all)
+ */
+ virtual bool notifyIntrinsicAnimationsDisabled() = 0;
+ };
+
+ typedef ::boost::shared_ptr< SubsettableShapeManager > SubsettableShapeManagerSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_SUBSETTABLESHAPEMANAGER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/tools.hxx b/slideshow/source/inc/tools.hxx
new file mode 100644
index 000000000000..706d26dc60ba
--- /dev/null
+++ b/slideshow/source/inc/tools.hxx
@@ -0,0 +1,407 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_TOOLS_HXX
+#define INCLUDED_SLIDESHOW_TOOLS_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <cppcanvas/color.hxx>
+
+#include "shapeattributelayer.hxx"
+#include "shape.hxx"
+#include "rgbcolor.hxx"
+#include "hslcolor.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/current_function.hpp>
+
+#include <functional>
+#include <cstdlib>
+#include <string.h> // for strcmp
+#include <algorithm>
+
+
+#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
+
+
+namespace com { namespace sun { namespace star { namespace beans {
+ struct NamedValue;
+} } } }
+namespace basegfx
+{
+ class B2DRange;
+ class B2DVector;
+ class B2IVector;
+ class B2DHomMatrix;
+}
+namespace cppcanvas{ class Canvas; }
+
+class GDIMetaFile;
+
+/* Definition of some animation tools */
+namespace slideshow
+{
+ namespace internal
+ {
+ class UnoView;
+ class Shape;
+ class ShapeAttributeLayer;
+
+ typedef ::boost::shared_ptr< GDIMetaFile > GDIMetaFileSharedPtr;
+
+ // xxx todo: remove with boost::hash when 1.33 is available
+ template <typename T>
+ struct hash : ::std::unary_function<T, ::std::size_t>
+ {
+ ::std::size_t operator()( T const& val ) const {
+ return hash_value(val);
+ }
+ };
+ template <typename T>
+ inline ::std::size_t hash_value( T * const& p )
+ {
+ ::std::size_t d = static_cast< ::std::size_t >(
+ reinterpret_cast< ::std::ptrdiff_t >(p) );
+ return d + (d >> 3);
+ }
+
+ // xxx todo: shift to namespace com::sun::star::uno when
+ // 1.33 is available
+ template <typename T>
+ inline ::std::size_t hash_value(
+ ::com::sun::star::uno::Reference<T> const& x )
+ {
+ // normalize to object root, because _only_ XInterface is defined
+ // to be stable during object lifetime:
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::uno::XInterface> const xRoot(
+ x, ::com::sun::star::uno::UNO_QUERY );
+ return hash<void *>()(xRoot.get());
+ }
+
+ /** Cycle mode of intrinsic animations
+ */
+ enum CycleMode
+ {
+ /// loop the animation back to back
+ CYCLE_LOOP,
+ /// loop, but play backwards from end to start
+ CYCLE_PINGPONGLOOP
+ };
+
+
+ // Value extraction from Any
+ // =========================
+
+ /// extract unary double value from Any
+ bool extractValue( double& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract int from Any
+ bool extractValue( sal_Int32& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract enum/constant group value from Any
+ bool extractValue( sal_Int16& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract color value from Any
+ bool extractValue( RGBColor& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract color value from Any
+ bool extractValue( HSLColor& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract plain string from Any
+ bool extractValue( ::rtl::OUString& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract bool value from Any
+ bool extractValue( bool& o_rValue,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /// extract double 2-tuple from Any
+ bool extractValue( basegfx::B2DTuple& o_rPair,
+ const ::com::sun::star::uno::Any& rSourceAny,
+ const boost::shared_ptr<Shape>& rShape,
+ const basegfx::B2DVector& rSlideBounds );
+
+ /** Search a sequence of NamedValues for a given element.
+
+ @return true, if the sequence contains the specified
+ element.
+ */
+ bool findNamedValue( ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::NamedValue > const& rSequence,
+ const ::com::sun::star::beans::NamedValue& rSearchKey );
+
+ /** Search a sequence of NamedValues for an element with a given name.
+
+ @param o_pRet
+ If non-NULL, receives the full NamedValue found (if it was
+ found, that is).
+
+ @return true, if the sequence contains the specified
+ element.
+ */
+ bool findNamedValue( ::com::sun::star::beans::NamedValue* o_pRet,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::NamedValue >& rSequence,
+ const ::rtl::OUString& rSearchString );
+
+ basegfx::B2DRange calcRelativeShapeBounds( const basegfx::B2DVector& rPageSize,
+ const basegfx::B2DRange& rShapeBounds );
+
+ /** Get the shape transformation from the attribute set
+
+ @param rBounds
+ Original shape bound rect (to substitute default attribute
+ layer values)
+
+ @param pAttr
+ Attribute set. Might be NULL (then, rBounds is used to set
+ a simple scale and translate of the unit rect to rBounds).
+ */
+ basegfx::B2DHomMatrix getShapeTransformation(
+ const basegfx::B2DRange& rBounds,
+ const boost::shared_ptr<ShapeAttributeLayer>& pAttr );
+
+ /** Get a shape's sprite transformation from the attribute set
+
+ @param rPixelSize
+ Pixel size of the sprite
+
+ @param rOrigSize
+ Original shape size (i.e. the size of the actual sprite
+ content, in the user coordinate system)
+
+ @param pAttr
+ Attribute set. Might be NULL (then, rBounds is used to set
+ a simple scale and translate of the unit rect to rBounds).
+
+ @return the transformation to be applied to the sprite.
+ */
+ basegfx::B2DHomMatrix getSpriteTransformation(
+ const basegfx::B2DVector& rPixelSize,
+ const basegfx::B2DVector& rOrigSize,
+ const boost::shared_ptr<ShapeAttributeLayer>& pAttr );
+
+ /** Calc update area for a shape.
+
+ This method calculates the 'covered' area for the shape,
+ i.e. the rectangle that is affected when rendering the
+ shape. Apart from applying the given transformation to the
+ shape rectangle, this method also takes attributes into
+ account, which further scale the output (e.g. character
+ sizes).
+
+ @param rUnitBounds
+ Shape bounds, in the unit rect coordinate space
+
+ @param rShapeTransform
+ Transformation matrix the shape should undergo.
+
+ @param pAttr
+ Current shape attributes
+ */
+ basegfx::B2DRange getShapeUpdateArea(
+ const basegfx::B2DRange& rUnitBounds,
+ const basegfx::B2DHomMatrix& rShapeTransform,
+ const boost::shared_ptr<ShapeAttributeLayer>& pAttr );
+
+ /** Calc update area for a shape.
+
+ This method calculates the 'covered' area for the shape,
+ i.e. the rectangle that is affected when rendering the
+ shape. The difference from the other getShapeUpdateArea()
+ method is the fact that this one works without
+ ShapeAttributeLayer, and only scales up the given shape
+ user coordinate bound rect. The method is typically used
+ to retrieve user coordinate system bound rects for shapes
+ which are smaller than the default unit bound rect
+ (because e.g. of subsetting)
+
+ @param rUnitBounds
+ Shape bounds, in the unit rect coordinate space
+
+ @param rShapeBounds
+ Current shape bounding box in user coordinate space.
+ */
+ basegfx::B2DRange getShapeUpdateArea( const basegfx::B2DRange& rUnitBounds,
+ const basegfx::B2DRange& rShapeBounds );
+
+ /** Calc output position and size of shape, according to given
+ attribute layer.
+
+ Rotations, shears etc. and not taken into account,
+ i.e. the returned rectangle is NOT the bounding box. Use
+ it as if aBounds.getMinimum() is the output position and
+ aBounds.getRange() the scaling of the shape.
+ */
+ basegfx::B2DRange getShapePosSize(
+ const basegfx::B2DRange& rOrigBounds,
+ const boost::shared_ptr<ShapeAttributeLayer>& pAttr );
+
+ /** Convert a plain UNO API 32 bit int to RGBColor
+ */
+ RGBColor unoColor2RGBColor( sal_Int32 );
+ /** Convert an IntSRGBA to plain UNO API 32 bit int
+ */
+ sal_Int32 RGBAColor2UnoColor( cppcanvas::Color::IntSRGBA );
+
+ /** Fill a plain rectangle on the given canvas with the given color
+ */
+ void fillRect( const boost::shared_ptr< cppcanvas::Canvas >& rCanvas,
+ const basegfx::B2DRange& rRect,
+ cppcanvas::Color::IntSRGBA aFillColor );
+
+ /** Init canvas with default background (white)
+ */
+ void initSlideBackground( const boost::shared_ptr< cppcanvas::Canvas >& rCanvas,
+ const basegfx::B2IVector& rSize );
+
+ /// Gets a random ordinal [0,n)
+ inline ::std::size_t getRandomOrdinal( const ::std::size_t n )
+ {
+ return static_cast< ::std::size_t >(
+ double(n) * rand() / (RAND_MAX + 1.0) );
+ }
+
+ /// To work around ternary operator in initializer lists
+ /// (Solaris compiler problems)
+ template <typename T>
+ inline T const & ternary_op(
+ const bool cond, T const & arg1, T const & arg2 )
+ {
+ if (cond)
+ return arg1;
+ else
+ return arg2;
+ }
+
+ template <typename ValueType>
+ inline bool getPropertyValue(
+ ValueType & rValue,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertySet> const & xPropSet,
+ rtl::OUString const & propName )
+ {
+ try {
+ const com::sun::star::uno::Any& a(
+ xPropSet->getPropertyValue( propName ) );
+ bool const bRet = (a >>= rValue);
+#if OSL_DEBUG_LEVEL > 0
+ if( !bRet )
+ OSL_TRACE( "%s: while retrieving property %s, cannot extract Any of type %s\n",
+ ::rtl::OUStringToOString( propName,
+ RTL_TEXTENCODING_ASCII_US ).getStr(),
+ BOOST_CURRENT_FUNCTION,
+ ::rtl::OUStringToOString( a.getValueTypeRef()->pTypeName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+#endif
+ return bRet;
+ }
+ catch (com::sun::star::uno::RuntimeException &)
+ {
+ throw;
+ }
+ catch (com::sun::star::uno::Exception &)
+ {
+ return false;
+ }
+ }
+
+ template <typename ValueType>
+ inline bool getPropertyValue(
+ com::sun::star::uno::Reference< ValueType >& rIfc,
+ com::sun::star::uno::Reference<
+ com::sun::star::beans::XPropertySet> const & xPropSet,
+ rtl::OUString const & propName )
+ {
+ try
+ {
+ const com::sun::star::uno::Any& a(
+ xPropSet->getPropertyValue( propName ));
+ rIfc.set( a,
+ com::sun::star::uno::UNO_QUERY );
+
+ bool const bRet = rIfc.is();
+#if OSL_DEBUG_LEVEL > 0
+ if( !bRet )
+ OSL_TRACE( "%s: while retrieving property %s, cannot extract Any of type %s to interface\n",
+ ::rtl::OUStringToOString( propName,
+ RTL_TEXTENCODING_ASCII_US ).getStr(),
+ BOOST_CURRENT_FUNCTION,
+ ::rtl::OUStringToOString( a.getValueTypeRef()->pTypeName,
+ RTL_TEXTENCODING_ASCII_US ).getStr() );
+#endif
+ return bRet;
+ }
+ catch (com::sun::star::uno::RuntimeException &)
+ {
+ throw;
+ }
+ catch (com::sun::star::uno::Exception &)
+ {
+ return false;
+ }
+ }
+
+ /// Get the content of the BoundRect shape property
+ basegfx::B2DRange getAPIShapeBounds( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape );
+
+ /// Get the content of the ZOrder shape property
+ double getAPIShapePrio( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::drawing::XShape >& xShape );
+
+ basegfx::B2IVector getSlideSizePixel( const basegfx::B2DVector& rSize,
+ const boost::shared_ptr<UnoView>& pView );
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_TOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/transitionfactory.hxx b/slideshow/source/inc/transitionfactory.hxx
new file mode 100644
index 000000000000..33296c5bacd4
--- /dev/null
+++ b/slideshow/source/inc/transitionfactory.hxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_TRANSITIONFACTORY_HXX
+#define INCLUDED_SLIDESHOW_TRANSITIONFACTORY_HXX
+
+#include <com/sun/star/animations/XTransitionFilter.hpp>
+#include <com/sun/star/presentation/XTransitionFactory.hpp>
+
+#include "animatableshape.hxx"
+#include "rgbcolor.hxx"
+#include "slide.hxx"
+#include "screenupdater.hxx"
+#include "animationactivity.hxx"
+#include "activitiesfactory.hxx"
+#include "numberanimation.hxx"
+#include "transitioninfo.hxx"
+#include "soundplayer.hxx"
+
+#include <boost/utility.hpp>
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /* Definition of Transitionfactory class */
+ class TransitionFactory : private boost::noncopyable
+ {
+ public:
+ /** Create a transition effect for shapes.
+
+ This method creates an AnimationActivity, which, when
+ run, performs the requested transition effect on the
+ given shape.
+
+ @param rParms
+ Collection of activity parameters, see ActivitiesFactory
+
+ @param rShape
+ Shape to animate
+
+ @param rShapeManager
+ ShapeManager, to manage shape animation
+
+ @param xTransition
+ The transition effect
+
+ @return the created activity, or NULL for no
+ transition effect
+ */
+ static AnimationActivitySharedPtr createShapeTransition(
+ const ActivitiesFactory::CommonParameters& rParms,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XTransitionFilter > const& xTransition );
+
+
+ /** Create a transition effect for slides.
+
+ This method creates a NumberAnimation, which,
+ when run, performs the requested transition effect
+ with the slide bitmaps.
+
+ @param rEnteringBitmap
+ Bitmap of the slide which 'enters' the screen.
+
+ @param rLeavingBitmap
+ Bitmap of the slide which 'leaves' the screen.
+
+ @param nTransitionType
+ Type of the transition (see XTransitionFilter)
+
+ @param nTransitionSubType
+ Subtype of the transition (see XTransitionFilter)
+
+ @param bTransitionDirection
+ Direction of the transition (see XTransitionFilter)
+
+ @param rTransitionFadeColor
+ Optional fade color for the transition
+
+ @return the created animation, or NULL for no
+ transition effect
+ */
+ static NumberAnimationSharedPtr createSlideTransition(
+ const SlideSharedPtr& rLeavingSlide,
+ const SlideSharedPtr& rEnteringSlide,
+ const UnoViewContainer& rViewContainer,
+ ScreenUpdater& rScreenUpdater,
+ EventMultiplexer& rEventMultiplexer,
+ const com::sun::star::uno::Reference<
+ com::sun::star::presentation::XTransitionFactory>&
+ xOptionalFactory,
+ sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType,
+ bool bTransitionDirection,
+ const RGBColor& rTransitionFadeColor,
+ const SoundPlayerSharedPtr& rSoundPlayer );
+
+ private:
+ static const TransitionInfo* getTransitionInfo(
+ sal_Int16 nTransitionType, sal_Int16 nTransitionSubType );
+ static const TransitionInfo* getRandomTransitionInfo();
+
+ static AnimationActivitySharedPtr createShapeTransition(
+ const ActivitiesFactory::CommonParameters& rParms,
+ const AnimatableShapeSharedPtr& rShape,
+ const ShapeManagerSharedPtr& rShapeManager,
+ const ::basegfx::B2DVector& rSlideSize,
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XTransitionFilter > const& xTransition,
+ sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType );
+
+ // static factory
+ TransitionFactory();
+ ~TransitionFactory();
+ };
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_TRANSITIONFACTORY_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/transitioninfo.hxx b/slideshow/source/inc/transitioninfo.hxx
new file mode 100644
index 000000000000..a6b60a09da70
--- /dev/null
+++ b/slideshow/source/inc/transitioninfo.hxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if ! defined INCLUDED_SLIDESHOW_TRANSITIONINFO_HXX
+#define INCLUDED_SLIDESHOW_TRANSITIONINFO_HXX
+
+#include <sal/types.h>
+
+
+namespace slideshow {
+namespace internal {
+
+struct TransitionInfo
+{
+ // the following two member serve as the search key
+ // for an incoming XTransitionFilter node
+ //
+ // {
+
+ sal_Int16 mnTransitionType;
+ sal_Int16 mnTransitionSubType;
+
+ // }
+ //
+
+ /** This enum classifies a transition type
+ */
+ enum TransitionClass
+ {
+ /// Invalid type
+ TRANSITION_INVALID,
+
+ /// Transition expressed by parametric clip polygon
+ TRANSITION_CLIP_POLYPOLYGON,
+
+ /// Transition expressed by hand-crafted function
+ TRANSITION_SPECIAL
+ };
+
+ /// class of effect handling
+ TransitionClass meTransitionClass;
+
+ /// Rotation angle of clip polygon
+ double mnRotationAngle;
+
+ /// X scaling of clip polygon (negative values mirror)
+ double mnScaleX;
+
+ /// Y scaling of clip polygon (negative values mirror)
+ double mnScaleY;
+
+ /** This enum determines the method how to reverse
+ a parametric clip polygon transition.
+
+ A reversed transition runs in the geometrically
+ opposite direction. For a left-to-right bar wipe, the
+ reversed transition is a right-to-left wipe, whereas
+ for an iris transition, the reversed mode will show
+ the target in the outer area (instead of in the inner
+ area, as in normal mode).
+ */
+ enum ReverseMethod
+ {
+ /** Ignore direction attribute altogether
+ (if it has no sensible meaning for this transition)
+ */
+ REVERSEMETHOD_IGNORE,
+
+ /** Revert by changing the direction of the parameter sweep
+ (from 1->0 instead of 0->1)
+ */
+ REVERSEMETHOD_INVERT_SWEEP,
+
+ /** Revert by subtracting the generated polygon from the
+ target bound rect
+ */
+ REVERSEMETHOD_SUBTRACT_POLYGON,
+
+ /** Combination of REVERSEMETHOD_INVERT_SWEEP and
+ REVERSEMETHOD_SUBTRACT_POLYGON.
+ */
+ REVERSEMETHOD_SUBTRACT_AND_INVERT,
+
+ /// Reverse by rotating polygon 180 degrees
+ REVERSEMETHOD_ROTATE_180,
+
+ /// Reverse by flipping polygon at the y (!) axis
+ REVERSEMETHOD_FLIP_X,
+
+ /// Reverse by flipping polygon at the x (!) axis
+ REVERSEMETHOD_FLIP_Y
+ };
+
+ /** Indicating the method to use when transition
+ should be 'reversed'.
+
+ @see ReverseMethod
+ */
+ ReverseMethod meReverseMethod;
+
+ /** When true, transition 'out' effects are realized
+ by inverting the parameter sweep direction (1->0
+ instead of 0->1). Otherwise, 'out' effects are
+ realized by changing inside and outside areas of
+ the parametric poly-polygon.
+ */
+ bool mbOutInvertsSweep;
+
+ /** when true, scale clip polygon isotrophically to
+ target size. when false, scale is
+ anisotrophically.
+ */
+ bool mbScaleIsotrophically;
+
+
+ /// Compare against type and subtype
+ class Comparator
+ {
+ sal_Int16 mnTransitionType;
+ sal_Int16 mnTransitionSubType;
+ public:
+ Comparator( sal_Int16 nTransitionType,
+ sal_Int16 nTransitionSubType )
+ : mnTransitionType( nTransitionType ),
+ mnTransitionSubType( nTransitionSubType ) {}
+ bool operator()( const TransitionInfo& rEntry ) const {
+ return rEntry.mnTransitionType == mnTransitionType &&
+ rEntry.mnTransitionSubType == mnTransitionSubType;
+ }
+ };
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_TRANSITIONINFO_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/unoview.hxx b/slideshow/source/inc/unoview.hxx
new file mode 100644
index 000000000000..6ac02b6d220a
--- /dev/null
+++ b/slideshow/source/inc/unoview.hxx
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_UNOVIEW_HXX
+#define INCLUDED_SLIDESHOW_UNOVIEW_HXX
+
+#include "view.hxx"
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <vector>
+
+namespace com { namespace sun { namespace star { namespace presentation
+{
+ class XSlideShowView;
+} } } }
+
+
+/* Definition of UnoView interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Extend View with UNO interface retrieval.
+
+ This interface extends View with an UNO interface
+ retrieval, to be used for Views which are set from
+ external API.
+ */
+ class UnoView : public View
+ {
+ public:
+ /** Retrieve the underlying UNO slide view.
+ */
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::presentation::XSlideShowView > getUnoView() const = 0;
+
+ /** Dispose view
+
+ This needs to be different from Disposable interface,
+ as the UNO XComponent also provides a dispose() (only
+ with a different calling convention under Windows).
+ */
+ virtual void _dispose() = 0;
+
+ /** Return whether the sound play back is enabled.
+ */
+ virtual bool isSoundEnabled (void) const = 0;
+
+ /** Tell the view whether it may play sounds. Disabling this
+ can be used to prevent different views to play the same
+ sounds at the same time.
+ */
+ virtual void setIsSoundEnabled (const bool bValue) = 0;
+ };
+
+ typedef ::boost::shared_ptr< UnoView > UnoViewSharedPtr;
+ typedef ::std::vector< UnoViewSharedPtr > UnoViewVector;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_UNOVIEW_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/unoviewcontainer.hxx b/slideshow/source/inc/unoviewcontainer.hxx
new file mode 100644
index 000000000000..994a72504407
--- /dev/null
+++ b/slideshow/source/inc/unoviewcontainer.hxx
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_UNOVIEWCONTAINER_HXX
+#define INCLUDED_SLIDESHOW_UNOVIEWCONTAINER_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+#include <vector>
+
+#include "unoview.hxx"
+
+
+namespace com { namespace sun { namespace star { namespace presentation
+{
+ class XSlideShowView;
+} } } }
+
+/* Definition of UnoViewContainer class */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Contains UnoViews
+ */
+ class UnoViewContainer : private boost::noncopyable
+ {
+ public:
+ UnoViewContainer();
+
+ /** Add a view to this container
+
+ @return true, if the view was successfully added
+ (false is e.g. returned, if the view was already
+ added)
+ */
+ bool addView( const UnoViewSharedPtr& rView );
+
+ /** Remove a previously added a view from this container
+
+ @return true, if this view was successfully removed, false
+ otherwise (e.g. if this view wasn't added in the first place)
+ */
+ bool removeView( const UnoViewSharedPtr& rView );
+
+ /** Remove a previously added a view from this container
+
+ @return the View object, if this view was successfully
+ removed, and an empty shared_ptr otherwise (e.g. if
+ this view wasn't added in the first place)
+ */
+ UnoViewSharedPtr removeView( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::presentation::XSlideShowView >& xView );
+
+ /// Dispose all stored views. Implies clear().
+ void dispose();
+
+ // the following parrots STL container concept methods
+ // ===================================================
+
+ std::size_t size() const { return maViews.size(); }
+ bool empty() const { return maViews.empty(); }
+
+ void clear() { maViews.clear(); }
+
+
+ UnoViewVector::iterator begin() { return maViews.begin(); }
+ UnoViewVector::const_iterator begin() const { return maViews.begin(); }
+ UnoViewVector::iterator end() { return maViews.end(); }
+ UnoViewVector::const_iterator end() const { return maViews.end(); }
+
+ private:
+ /// All added views
+ UnoViewVector maViews;
+ };
+
+ typedef ::boost::shared_ptr< UnoViewContainer > UnoViewContainerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_UNOVIEWCONTAINER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/usereventqueue.hxx b/slideshow/source/inc/usereventqueue.hxx
new file mode 100644
index 000000000000..c1d1f6cfbad2
--- /dev/null
+++ b/slideshow/source/inc/usereventqueue.hxx
@@ -0,0 +1,329 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_USEREVENTQUEUE_HXX
+#define INCLUDED_SLIDESHOW_USEREVENTQUEUE_HXX
+
+#include <com/sun/star/animations/XAnimationNode.hpp>
+
+#include "eventmultiplexer.hxx"
+#include "eventqueue.hxx"
+#include "shape.hxx"
+
+#include <boost/noncopyable.hpp>
+
+/* Definition of UserEventQueue class */
+
+namespace slideshow {
+namespace internal {
+
+class PlainEventHandler;
+class AllAnimationEventHandler;
+class ShapeClickEventHandler;
+class ClickEventHandler;
+class CursorManager;
+class SkipEffectEventHandler;
+class RewindEffectEventHandler;
+class MouseEnterHandler;
+class MouseLeaveHandler;
+
+/** This class schedules user-activated events.
+
+ This class registeres at the EventMultiplexer and fires
+ events registered for certain user actions. Note that all
+ events will not be fired immediately after the user action
+ occured, but always added to the EventQueue (and fired the
+ next time that queue is processed). Which is actually a
+ feature.
+
+ Conceptually, an event is an object that typically is
+ fired only once. After that, the event is exhausted, and
+ should be discarded. Therefore, all events registered on
+ this object are fired and then all references to them are
+ removed.
+*/
+class UserEventQueue : private ::boost::noncopyable
+{
+public:
+ /** Create a user event queue
+
+ @param rEventMultiplexer
+ The slideshow-global event source, where this class
+ registeres its event handlers.
+
+ @param rEventQueue
+ Reference to the main event queue. Since we hold this
+ object by plain reference, it must live longer than we
+ do. On the other hand, that queue must not fire events
+ after this object is destroyed, since we might
+ schedule events there which itself contain plain
+ references to this object. Basically, EventQueue and
+ UserEventQueue should have the same lifetime, and since
+ this is not possible, both must be destructed in a
+ phased mode: first clear both of any remaining events,
+ then destruct them.
+ */
+ UserEventQueue( EventMultiplexer& rMultiplexer,
+ EventQueue& rEventQueue,
+ CursorManager& rCursorManager );
+ ~UserEventQueue();
+
+ /** Query whether there are any events still pending.
+ */
+ bool isEmpty() const;
+
+ /** Clear all registered events.
+
+ This method clears all registered, but
+ not-yet-executed events. This comes in handy when
+ force-ending a slide, to avoid interference with the
+ next slide's event registration.
+ */
+ void clear();
+
+ /** Set advance on click behaviour.
+
+ @param bAdvanceOnClick
+ When true, a click somewhere on the slide will also
+ generate next effect event. In this case, it is
+ irrelevant where on the slide the mouse is clicked,
+ i.e. the shape need not be hit by the mouse.
+ */
+ void setAdvanceOnClick( bool bAdvanceOnClick );
+
+ /** Register an event that will be fired when the slide is
+ just shown.
+
+ Note that <em>all</em> registered events will be fired
+ when the slide start occurs. This is in contrast to
+ the mouse events below.
+ */
+ void registerSlideStartEvent( const EventSharedPtr& rEvent );
+
+ /** Register an event that will be fired when the slide is
+ about to vanish.
+
+ Note that <em>all</em> registered events will be fired
+ when the slide end occurs. This is in contrast to
+ the mouse events below.
+ */
+ void registerSlideEndEvent( const EventSharedPtr& rEvent );
+
+ /** Register an event that will be fired when the given
+ animation node starts.
+
+ Note that <em>all</em> registered events will be fired
+ when the animation start occurs. This is in contrast to
+ the mouse events below.
+ */
+ void registerAnimationStartEvent(
+ const EventSharedPtr& rEvent,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode>& xNode );
+
+ /** Register an event that will be fired when the given
+ animation node ends its active duration.
+
+ Note that <em>all</em> registered events will be fired
+ when the animation end occurs. This is in contrast to
+ the mouse events below.
+ */
+ void registerAnimationEndEvent(
+ const EventSharedPtr& rEvent,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode>& xNode );
+
+ /** Register an event that will be fired when audio output
+ stopped for the given animation node.
+
+ Note that <em>all</em> registered events will be fired
+ when the audio stopping occurs. This is in contrast to
+ the mouse events below.
+ */
+ void registerAudioStoppedEvent(
+ const EventSharedPtr& rEvent,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::animations::XAnimationNode>& xNode );
+
+ /** Register an event that is fired when a shape is clicked
+
+ For every mouse click, only one of the events
+ registered here is fired. The order of fired events is
+ the order of registration, i.e. the first event
+ registered will be the one fired for the first mouse
+ click on the given shape.
+ */
+ void registerShapeClickEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape );
+
+ /** Registes an event that is fired when the current effects(s)
+ are skipped, .e.g. when the left mouse button is pressed.
+ Then, all registered events are fired and removed from this
+ queue. After firing, a next effect event is issued to this
+ queue to start the next effect.
+ @param pEvent
+ The event to execute when skipping the current effect.
+ @param bSkipTriggersNextEffect
+ When <TRUE/> then after skipping the current effect the next
+ effect is triggered. When <FALSE/> then the next effect is not
+ triggered.
+ */
+ void registerSkipEffectEvent(
+ EventSharedPtr const& pEvent,
+ const bool bSkipTriggersNextEffect);
+
+ /** Registes an event that is fired when the current effects(s)
+ are rewound, .e.g. when the right mouse button is pressed.
+ Then, all registered events are fired and removed from this
+ queue.
+ */
+ void registerRewindEffectEvent( EventSharedPtr const& rEvent );
+
+ /** Register an event that is fired to show the next event
+
+ For every next effect event, only one of the events
+ registered here is fired. The order of fired events is
+ the order of registration, i.e. the first event
+ registered will be the one fired for the first mouse
+ click. When advance-on-click (see method
+ setAdvanceOnClick()) is enabled, a mouse click
+ somewhere on the slide will also generate a next
+ effect event. In this case, it is irrelevant where on
+ the slide the mouse is clicked, i.e. the shape need
+ not be hit by the mouse.
+ */
+ void registerNextEffectEvent( const EventSharedPtr& rEvent );
+
+ /** Register an event that is fired on a double mouse
+ click on a shape
+
+ For every mouse double click, only one of the events
+ registered here is fired. The order of fired events is
+ the order of registration, i.e. the first event
+ registered will be the one fired for the first mouse
+ double click. It is irrelevant where on the slide the
+ mouse is clicked, i.e. the shape need not be hit by
+ the mouse.
+ */
+ void registerShapeDoubleClickEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape );
+
+ /** Register an event that is fired on a double mouse click
+
+ For every mouse double click, only one of the events
+ registered here is fired. The order of fired events is
+ the order of registration, i.e. the first event
+ registered will be the one fired for the first mouse
+ double click. It is irrelevant where on the slide the
+ mouse is clicked, i.e. the shape need not be hit by
+ the mouse.
+ */
+ void registerDoubleClickEvent( const EventSharedPtr& rEvent );
+
+ /** Register an event that is fired when the mouse enters
+ the area of the given shape
+
+ For every enter, only one of the events registered
+ here is fired. The order of fired events is the order
+ of registration, i.e. the first event registered will
+ be the one fired for the first time the mouse enters
+ the given shape.
+ */
+ void registerMouseEnterEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape );
+
+ /** Register an event that is fired when the mouse leaves
+ the area of the given shape
+
+ For every leave, only one of the events registered
+ here is fired. The order of fired events is the order
+ of registration, i.e. the first event registered will
+ be the one fired for the first time the mouse leaves
+ the given shape area.
+ */
+ void registerMouseLeaveEvent( const EventSharedPtr& rEvent,
+ const ShapeSharedPtr& rShape );
+
+ /** Typically skipping the current effect is triggered by mouse clicks
+ or key presses that trigger the next effect. This method allows the
+ skipping of effects to be triggered programatically.
+ */
+ void callSkipEffectEventHandler (void);
+
+private:
+ /** Generically register an event on one of the handlers.
+
+ If the handler is not yet created, do that and
+ register it via the Functor
+ */
+ template< typename Handler, typename Functor >
+ void registerEvent( ::boost::shared_ptr< Handler >& rHandler,
+ const EventSharedPtr& rEvent,
+ const Functor& rRegistrationFunctor );
+
+ /** Generically register an event on one of the handlers.
+
+ If the handler is not yet created, do that and
+ register it via the Functor. This version of the
+ registerEvent method takes an additional parameter
+ rArg, which is passed as the second argument to
+ rHandler's addEvent() method.
+ */
+ template< typename Handler, typename Arg, typename Functor >
+ void registerEvent( ::boost::shared_ptr< Handler >& rHandler,
+ const EventSharedPtr& rEvent,
+ const Arg& rArg,
+ const Functor& rRegistrationFunctor );
+
+ EventMultiplexer& mrMultiplexer;
+ EventQueue& mrEventQueue;
+ CursorManager& mrCursorManager;
+
+ ::boost::shared_ptr<PlainEventHandler> mpStartEventHandler;
+ ::boost::shared_ptr<PlainEventHandler> mpEndEventHandler;
+ ::boost::shared_ptr<AllAnimationEventHandler> mpAnimationStartEventHandler;
+ ::boost::shared_ptr<AllAnimationEventHandler> mpAnimationEndEventHandler;
+ ::boost::shared_ptr<AllAnimationEventHandler> mpAudioStoppedEventHandler;
+ ::boost::shared_ptr<ShapeClickEventHandler> mpShapeClickEventHandler;
+ ::boost::shared_ptr<ClickEventHandler> mpClickEventHandler;
+ ::boost::shared_ptr<SkipEffectEventHandler> mpSkipEffectEventHandler;
+ ::boost::shared_ptr<RewindEffectEventHandler> mpRewindEffectEventHandler;
+ ::boost::shared_ptr<ShapeClickEventHandler> mpShapeDoubleClickEventHandler;
+ ::boost::shared_ptr<ClickEventHandler> mpDoubleClickEventHandler;
+ ::boost::shared_ptr<MouseEnterHandler> mpMouseEnterHandler;
+ ::boost::shared_ptr<MouseLeaveHandler> mpMouseLeaveHandler;
+
+ bool mbAdvanceOnClick;
+};
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_USEREVENTQUEUE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/userpainteventhandler.hxx b/slideshow/source/inc/userpainteventhandler.hxx
new file mode 100644
index 000000000000..c7a56fc3613c
--- /dev/null
+++ b/slideshow/source/inc/userpainteventhandler.hxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_USERPAINTEVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_USERPAINTEVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+
+/* Definition of UserPaintEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class RGBColor;
+
+ /** Interface for handling user paint state changes.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle user paint events.
+ */
+ class UserPaintEventHandler
+ {
+ public:
+ virtual ~UserPaintEventHandler() {}
+ virtual bool colorChanged( RGBColor const& rUserColor ) = 0;
+ virtual bool widthChanged( double nUserStrokeWidth ) = 0;
+ virtual bool eraseAllInkChanged(bool const& rEraseAllInk) =0;
+ virtual bool eraseInkWidthChanged(sal_Int32 rEraseInkSize) =0;
+ virtual bool switchEraserMode() = 0;
+ virtual bool switchPenMode() = 0;
+ virtual bool disable() = 0;
+ };
+
+ typedef ::boost::shared_ptr< UserPaintEventHandler > UserPaintEventHandlerSharedPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_USERPAINTEVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/view.hxx b/slideshow/source/inc/view.hxx
new file mode 100644
index 000000000000..43fc5f90db05
--- /dev/null
+++ b/slideshow/source/inc/view.hxx
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEW_HXX
+#define INCLUDED_SLIDESHOW_VIEW_HXX
+
+#include "viewlayer.hxx"
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+
+namespace basegfx { class B2DRange; class B2DVector; }
+
+
+/* Definition of View interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class View : public ViewLayer
+ {
+ public:
+ /** Create a new view layer for this view
+
+ @param rLayerBounds
+ Specifies the bound rect of the layer relative to the
+ user view coordinate system.
+
+ This method sets the bounds of the view layer in
+ document coordinates (i.e. 'logical' coordinates). The
+ resulting transformation is then concatenated with the
+ underlying view transformation, returned by the
+ getTransformation() method.
+ */
+ virtual ViewLayerSharedPtr createViewLayer( const basegfx::B2DRange& rLayerBounds ) const = 0;
+
+ /** Update screen representation from backbuffer
+ */
+ virtual bool updateScreen() const = 0;
+
+ /** Paint screen content unconditionally from backbuffer
+ */
+ virtual bool paintScreen() const = 0;
+
+ /** Set the size of the user view coordinate system.
+
+ This method sets the width and height of the view in
+ document coordinates (i.e. 'logical' coordinates). The
+ resulting transformation is then concatenated with the
+ underlying view transformation, returned by the
+ getTransformation() method.
+ */
+ virtual void setViewSize( const ::basegfx::B2DVector& ) = 0;
+
+ /** Change the view's mouse cursor.
+
+ @param nPointerShape
+ One of the ::com::sun::star::awt::SystemPointer
+ constant group members.
+ */
+ virtual void setCursorShape( sal_Int16 nPointerShape ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< View > ViewSharedPtr;
+ typedef ::std::vector< ViewSharedPtr > ViewVector;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEW_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/vieweventhandler.hxx b/slideshow/source/inc/vieweventhandler.hxx
new file mode 100644
index 000000000000..1b97d613a32a
--- /dev/null
+++ b/slideshow/source/inc/vieweventhandler.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWEVENTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_VIEWEVENTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include "unoview.hxx"
+
+
+/* Definition of ViewEventHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling view events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle view events.
+ */
+ class ViewEventHandler
+ {
+ public:
+ virtual ~ViewEventHandler() {}
+
+ /** Notify new view.
+
+ @param rView
+ The newly added view
+ */
+ virtual void viewAdded( const UnoViewSharedPtr& rView ) = 0;
+
+ /** Notify removed view.
+
+ @param rView
+ The removed view
+ */
+ virtual void viewRemoved( const UnoViewSharedPtr& rView ) = 0;
+
+ /** Notify changed view.
+
+ Reasons for a viewChanged notification can be
+ different view size, transformation, or other device
+ properties (color resolution or profile, etc.)
+
+ @param rView
+ The changed view
+ */
+ virtual void viewChanged( const UnoViewSharedPtr& rView ) = 0;
+
+ /** Notify that all views changed.
+
+ Reasons for a viewChanged notification can be
+ different view size, transformation, or other device
+ properties (color resolution or profile, etc.)
+
+ Note that this method avoids hidden inefficiencies
+ (O(n^2) behaviour when viewChanged() needs to perform
+ linear searches)
+ */
+ virtual void viewsChanged() = 0;
+ };
+
+ typedef ::boost::shared_ptr< ViewEventHandler > ViewEventHandlerSharedPtr;
+ typedef ::boost::weak_ptr< ViewEventHandler > ViewEventHandlerWeakPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWEVENTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/viewlayer.hxx b/slideshow/source/inc/viewlayer.hxx
new file mode 100644
index 000000000000..c2351a517f3a
--- /dev/null
+++ b/slideshow/source/inc/viewlayer.hxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWLAYER_HXX
+#define INCLUDED_SLIDESHOW_VIEWLAYER_HXX
+
+#include <sal/config.h>
+#include <boost/shared_ptr.hpp>
+
+namespace basegfx
+{
+ class B1DRange;
+ class B2DRange;
+ class B2DVector;
+ class B2DHomMatrix;
+ class B2DPolyPolygon;
+}
+namespace cppcanvas
+{
+ class Canvas;
+ class CustomSprite;
+}
+
+
+/* Definition of ViewLayer interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ class View;
+
+ class ViewLayer
+ {
+ public:
+ virtual ~ViewLayer() {}
+
+ /** Query whether layer displays on given view.
+
+ @return true, if this layer displays on the given
+ view.
+ */
+ virtual bool isOnView(boost::shared_ptr<View> const& rView) const = 0;
+
+ /** Get the associated canvas of this layer.
+
+ The canvas returned by this method must not change, as
+ long as this object is alive.
+ */
+ virtual boost::shared_ptr< cppcanvas::Canvas > getCanvas() const = 0;
+
+ /** Clear the clipped view layer area
+
+ This method clears the area inside the clip polygon,
+ if none is set, the transformed unit rectangle of the
+ view.
+ */
+ virtual void clear() const = 0;
+
+ /** Clear the complete view
+
+ This method clears the full view area (not only the
+ transformed unit rectangle, or within the clip). If
+ this ViewLayer represents the background layer, the
+ whole XSlideShowView is cleared. If this ViewLayer is
+ implemented using sprites (i.e. one of the upper
+ layers), the sprite is cleared to fully transparent.
+ */
+ virtual void clearAll() const = 0;
+
+ /** Create a sprite for this layer
+
+ @param rSpriteSizePixel
+ Sprite size in device pixel
+
+ @param nPriority
+ Sprite priority. This value determines the priority of
+ this sprite, relative to all other sprites of this
+ ViewLayer. The higher the priority, the closer to the
+ foreground the sprite will be.
+
+ @return the sprite, or NULL on failure (or if this
+ canvas does not support sprites).
+ */
+ virtual boost::shared_ptr< cppcanvas::CustomSprite >
+ createSprite( const basegfx::B2DVector& rSpriteSizePixel,
+ double nPriority ) const = 0;
+
+ /** Set the layer priority range
+
+ This method influences the relative priority of this
+ layer, i.e. the z position in relation to other layers
+ on the parent view. The higher the priority range, the
+ further in front the layer resides.
+
+ @param rRange
+ Priority range, must be in the range [0,1]
+ */
+ virtual void setPriority( const basegfx::B1DRange& rRange ) = 0;
+
+ /** Get the overall view transformation.
+
+ This method should <em>not</em> simply return the
+ underlying canvas' transformation, but rather provide
+ a layer above that. This enables clients of the
+ slideshow to set their own user space transformation
+ at the canvas, whilst the slideshow adds their
+ transformation on top of that. Concretely, this method
+ returns the user transform (implicitely calculated
+ from the setViewSize() method), combined with the view
+ transformation.
+ */
+ virtual basegfx::B2DHomMatrix getTransformation() const = 0;
+
+ /** Get the overall view transformation.
+
+ Same transformation as with getTransformation(), only
+ that you can safely use this one to position sprites
+ on screen (no ViewLayer offsets included whatsoever).
+ */
+ virtual basegfx::B2DHomMatrix getSpriteTransformation() const = 0;
+
+ /** Set clipping on this view layer.
+
+ @param rClip
+ Clip poly-polygon to set. The polygon is interpreted
+ in the user coordinate system, i.e. the view layer has
+ the size as given by setViewSize() on its
+ corresponding View.
+ */
+ virtual void setClip( const basegfx::B2DPolyPolygon& rClip ) = 0;
+
+ /** Resize this view layer.
+
+ @param rArea
+ New area to cover. The area is interpreted in the user
+ coordinate system, i.e. relative to the size as given
+ by setViewSize() on the corresponding View.
+
+ @return true, if layer was actually resized (which
+ invalidates its content)
+ */
+ virtual bool resize( const basegfx::B2DRange& rArea ) = 0;
+
+ };
+
+ typedef boost::shared_ptr< ViewLayer > ViewLayerSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWLAYER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/viewrepainthandler.hxx b/slideshow/source/inc/viewrepainthandler.hxx
new file mode 100644
index 000000000000..a361825a12aa
--- /dev/null
+++ b/slideshow/source/inc/viewrepainthandler.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWREPAINTHANDLER_HXX
+#define INCLUDED_SLIDESHOW_VIEWREPAINTHANDLER_HXX
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+#include "unoview.hxx"
+
+
+/* Definition of ViewRepaintHandler interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+
+ /** Interface for handling view repaint events.
+
+ Classes implementing this interface can be added to an
+ EventMultiplexer object, and are called from there to
+ handle view repaint events.
+ */
+ class ViewRepaintHandler
+ {
+ public:
+ virtual ~ViewRepaintHandler() {}
+
+ /** Notify clobbered view.
+
+ Reasons for a viewChanged notification can be
+ different view size, transformation, or other device
+ properties (color resolution or profile, etc.)
+
+ @param rView
+ The changed view
+ */
+ virtual void viewClobbered( const UnoViewSharedPtr& rView ) = 0;
+ };
+
+ typedef ::boost::shared_ptr< ViewRepaintHandler > ViewRepaintHandlerSharedPtr;
+ typedef ::boost::weak_ptr< ViewRepaintHandler > ViewRepaintHandlerWeakPtr;
+
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWREPAINTHANDLER_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/viewupdate.hxx b/slideshow/source/inc/viewupdate.hxx
new file mode 100644
index 000000000000..7cddf1cbecd1
--- /dev/null
+++ b/slideshow/source/inc/viewupdate.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SLIDESHOW_VIEWUPDATE_HXX
+#define INCLUDED_SLIDESHOW_VIEWUPDATE_HXX
+
+#include "disposable.hxx"
+#include "view.hxx"
+#include <boost/shared_ptr.hpp>
+
+/* Definition of ViewUpdate interface */
+
+namespace slideshow
+{
+ namespace internal
+ {
+ /** Interface for something that can perform view updates.
+
+ Use this interface for objects that perform view updates
+ from time to time, e.g. slide content. Availability of
+ updates can be queried, and subsequently performed.
+ */
+ class ViewUpdate : public Disposable
+ {
+ public:
+ /** Perform the update action on all views
+
+ @return true, if the update was performed
+ successfully, false otherwise.
+ */
+ virtual bool update() = 0;
+
+ /** Perform the update action on given view only
+
+ @return true, if the update was performed
+ successfully, false otherwise.
+ */
+ virtual bool update( ViewSharedPtr const& rView ) = 0;
+
+ /** Query whether updates are pending
+
+ @return true, if updates are pending. Calling update()
+ subsequently will perform the pending update then.
+ */
+ virtual bool needsUpdate() const = 0;
+ };
+
+ typedef ::boost::shared_ptr< ViewUpdate > ViewUpdateSharedPtr;
+ }
+}
+
+#endif /* INCLUDED_SLIDESHOW_VIEWUPDATE_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/inc/wakeupevent.hxx b/slideshow/source/inc/wakeupevent.hxx
new file mode 100644
index 000000000000..602993ebd98f
--- /dev/null
+++ b/slideshow/source/inc/wakeupevent.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_SLIDESHOW_WAKEUPEVENT_HXX
+#define INCLUDED_SLIDESHOW_WAKEUPEVENT_HXX
+
+#include <canvas/elapsedtime.hxx>
+
+#include "event.hxx"
+#include "activitiesqueue.hxx"
+
+#include <boost/bind.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace slideshow {
+namespace internal {
+
+/** Little helper class, used to set Activities active again
+ after some sleep period.
+
+ Clients can use this class to schedule wakeup events at
+ the EventQueue, to avoid busy-waiting for the next
+ discrete time instant.
+*/
+class WakeupEvent : public Event,
+ private ::boost::noncopyable
+{
+public:
+ WakeupEvent(
+ ::boost::shared_ptr< ::canvas::tools::ElapsedTime > const& pTimeBase,
+ ActivitiesQueue & rActivityQueue );
+
+ virtual void dispose();
+ virtual bool fire();
+ virtual bool isCharged() const;
+ virtual double getActivationTime( double nCurrentTime ) const;
+
+ /// Start the internal timer
+ void start();
+
+ /** Set the next timeout this object should generate.
+
+ @param nextTime
+ Absolute time, measured from the last start() call,
+ when this event should wakeup the Activity again. If
+ your time is relative, simply call start() just before
+ every setNextTimeout() call.
+ */
+ void setNextTimeout( double nextTime );
+
+ /** Set activity to wakeup.
+
+ The activity given here will be reinserted into the
+ ActivitiesQueue, once the timeout is reached.
+ */
+ void setActivity( const ActivitySharedPtr& rActivity );
+
+private:
+ ::canvas::tools::ElapsedTime maTimer;
+ double mnNextTime;
+ ActivitySharedPtr mpActivity;
+ ActivitiesQueue& mrActivityQueue;
+};
+
+typedef ::boost::shared_ptr< WakeupEvent > WakeupEventSharedPtr;
+
+} // namespace internal
+} // namespace presentation
+
+#endif /* INCLUDED_SLIDESHOW_WAKEUPEVENT_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */