summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drawinglayer/source/primitive2d/animatedprimitive2d.cxx9
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx516
-rw-r--r--include/drawinglayer/primitive2d/animatedprimitive2d.hxx9
3 files changed, 395 insertions, 139 deletions
diff --git a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
index 03712fbee3d0..d832a43581b6 100644
--- a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
@@ -31,6 +31,15 @@ namespace drawinglayer
{
namespace primitive2d
{
+ void AnimatedSwitchPrimitive2D::setAnimationEntry(const animation::AnimationEntry& rNew)
+ {
+ // delete cloned animation description
+ delete mpAnimationEntry;
+
+ // clone given animation description
+ mpAnimationEntry = rNew.clone();
+ }
+
AnimatedSwitchPrimitive2D::AnimatedSwitchPrimitive2D(
const animation::AnimationEntry& rAnimationEntry,
const Primitive2DContainer& rChildren,
diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
index 87d3959cebf9..bd62db88bec4 100644
--- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
@@ -25,6 +25,7 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/numeric/ftools.hxx>
@@ -37,152 +38,413 @@
#include <vcl/svapp.hxx>
#include <vcl/metaact.hxx>
-namespace
+namespace drawinglayer
{
- struct animationStep
+ namespace primitive2d
{
- BitmapEx maBitmapEx;
- sal_uInt32 mnTime;
- };
+ class AnimatedGraphicPrimitive2D : public AnimatedSwitchPrimitive2D
+ {
+ private:
+ /// the geometric definition
+ basegfx::B2DHomMatrix maTransform;
- class animatedBitmapExPreparator
- {
- ::Animation maAnimation;
- ::std::vector< animationStep > maSteps;
+ /** the Graphic with all its content possibilities, here only
+ animated is allowed and gets checked by isValidData().
+ an instance of Graphic is used here since it's ref-counted
+ and thus a safe cpoy for now
+ */
+ const Graphic maGraphic;
- sal_uInt32 generateStepTime(sal_uInt32 nIndex) const;
+ /// local animation processing data, excerpt from maGraphic
+ ::Animation maAnimation;
- public:
- explicit animatedBitmapExPreparator(const Graphic& rGraphic);
+ /// the on-demand created VirtualDevices for frame creation
+ ScopedVclPtrInstance< VirtualDevice > maVirtualDevice;
+ ScopedVclPtrInstance< VirtualDevice > maVirtualDeviceMask;
- sal_uInt32 count() const { return maSteps.size(); }
- sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); }
- sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; }
- const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; }
- };
+ // index of the next frame that would be regularly prepared
+ sal_uInt32 mnNextFrameToPrepare;
- sal_uInt32 animatedBitmapExPreparator::generateStepTime(sal_uInt32 nIndex) const
- {
- const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex));
- sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10);
+ /// buffering of 1st frame (always active)
+ Primitive2DReference maBufferedFirstFrame;
- // Take care of special value for MultiPage TIFFs. ATM these shall just
- // show their first page. Later we will offer some switching when object
- // is selected.
- if(ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait)
- {
- // ATM the huge value would block the timer, so
- // use a long time to show first page (whole day)
- nWaitTime = 100 * 60 * 60 * 24;
- }
+ /// buffering of all frames
+ Primitive2DContainer maBufferedPrimitives;
+ bool mbBufferingAllowed;
- // Bad trap: There are animated gifs with no set WaitTime (!).
- // In that case use a default value.
- if(0L == nWaitTime)
- {
- nWaitTime = 100L;
- }
+ /// set if the animation is huge so that just always the next frame
+ /// is used instead of using timing
+ bool mbHugeSize;
- return nWaitTime;
- }
+ /// helper methods
+ bool isValidData() const
+ {
+ return (GRAPHIC_BITMAP == maGraphic.GetType()
+ && maGraphic.IsAnimated()
+ && maAnimation.Count());
+ }
- animatedBitmapExPreparator::animatedBitmapExPreparator(const Graphic& rGraphic)
- : maAnimation(rGraphic.GetAnimation())
- {
- OSL_ENSURE(GRAPHIC_BITMAP == rGraphic.GetType() && rGraphic.IsAnimated(), "animatedBitmapExPreparator: graphic is not animated (!)");
+ void ensureVirtualDeviceSizeAndState()
+ {
+ if (isValidData())
+ {
+ const Size aCurrent(maVirtualDevice->GetOutputSizePixel());
+ const Size aTarget(maAnimation.GetDisplaySizePixel());
- // #128539# secure access to Animation, looks like there exist animated GIFs out there
- // with a step count of zero
- if(maAnimation.Count())
- {
- ScopedVclPtrInstance< VirtualDevice > aVirtualDevice(*Application::GetDefaultDevice());
- ScopedVclPtrInstance< VirtualDevice > aVirtualDeviceMask(*Application::GetDefaultDevice(),
- DeviceFormat::BITMASK);
-
- // Prepare VirtualDevices and their states
- aVirtualDevice->EnableMapMode(false);
- aVirtualDeviceMask->EnableMapMode(false);
- aVirtualDevice->SetOutputSizePixel(maAnimation.GetDisplaySizePixel());
- aVirtualDeviceMask->SetOutputSizePixel(maAnimation.GetDisplaySizePixel());
- aVirtualDevice->Erase();
- aVirtualDeviceMask->Erase();
-
- for(size_t a(0); a < maAnimation.Count(); a++)
+ if (aCurrent != aTarget)
+ {
+ maVirtualDevice->EnableMapMode(false);
+ maVirtualDeviceMask->EnableMapMode(false);
+ maVirtualDevice->SetOutputSizePixel(aTarget);
+ maVirtualDeviceMask->SetOutputSizePixel(aTarget);
+ }
+
+ maVirtualDevice->Erase();
+ maVirtualDeviceMask->Erase();
+ }
+ }
+
+ sal_uInt32 generateStepTime(sal_uInt32 nIndex) const
{
- animationStep aNextStep;
- aNextStep.mnTime = generateStepTime(a);
+ const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex));
+ sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10);
+
+ // Take care of special value for MultiPage TIFFs. ATM these shall just
+ // show their first page. Later we will offer some switching when object
+ // is selected.
+ if (ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait)
+ {
+ // ATM the huge value would block the timer, so
+ // use a long time to show first page (whole day)
+ nWaitTime = 100 * 60 * 60 * 24;
+ }
- // prepare step
- const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(a));
+ // Bad trap: There are animated gifs with no set WaitTime (!).
+ // In that case use a default value.
+ if (0L == nWaitTime)
+ {
+ nWaitTime = 100L;
+ }
+
+ return nWaitTime;
+ }
- switch(rAnimBitmap.eDisposal)
+ void createAndSetAnimationTiming()
+ {
+ if (isValidData())
{
- case Disposal::Not:
+ animation::AnimationEntryLoop aAnimationLoop(maAnimation.GetLoopCount() ? maAnimation.GetLoopCount() : 0xffff);
+ const sal_uInt32 nCount(maAnimation.Count());
+
+ for (sal_uInt32 a(0); a < nCount; a++)
{
- aVirtualDevice->DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
- Bitmap aMask = rAnimBitmap.aBmpEx.GetMask();
+ const sal_uInt32 aStepTime(generateStepTime(a));
+ const animation::AnimationEntryFixed aTime((double)aStepTime, (double)a / (double)nCount);
- if(aMask.IsEmpty())
- {
- const Point aEmpty;
- const Rectangle aRect(aEmpty, aVirtualDeviceMask->GetOutputSizePixel());
- const Wallpaper aWallpaper(COL_BLACK);
- aVirtualDeviceMask->DrawWallpaper(aRect, aWallpaper);
- }
- else
+ aAnimationLoop.append(aTime);
+ }
+
+ animation::AnimationEntryList aAnimationEntryList;
+ aAnimationEntryList.append(aAnimationLoop);
+
+ setAnimationEntry(aAnimationEntryList);
+ }
+ }
+
+ Primitive2DReference createFromBuffer() const
+ {
+ // create BitmapEx by extracting from VirtualDevices
+ const Bitmap aMainBitmap(maVirtualDevice->GetBitmap(Point(), maVirtualDevice->GetOutputSizePixel()));
+#if defined(MACOSX) || defined(IOS)
+ const AlphaMask aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
+#else
+ const Bitmap aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
+#endif
+
+ return Primitive2DReference(
+ new BitmapPrimitive2D(
+ BitmapEx(aMainBitmap, aMaskBitmap),
+ getTransform()));
+ }
+
+ void checkSafeToBuffer(sal_uInt32 nIndex)
+ {
+ if (mbBufferingAllowed)
+ {
+ // all frames buffered
+ if (mbBufferingAllowed && maBufferedPrimitives.size() && nIndex < maBufferedPrimitives.size())
+ {
+ if (!maBufferedPrimitives[nIndex].is())
{
- BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask);
- aVirtualDeviceMask->DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask);
- }
+ maBufferedPrimitives[nIndex] = createFromBuffer();
- break;
+ // check if buffering is complete
+ bool bBufferingComplete(true);
+
+ for (sal_uInt32 a(0); bBufferingComplete && a < maBufferedPrimitives.size(); a++)
+ {
+ bBufferingComplete = maBufferedPrimitives[a].is();
+ }
+
+ if (bBufferingComplete)
+ {
+ maVirtualDevice.disposeAndClear();
+ maVirtualDeviceMask.disposeAndClear();
+ }
+ }
+ }
+ }
+ else
+ {
+ // always buffer first frame
+ if (0 == nIndex && !maBufferedFirstFrame.is())
+ {
+ maBufferedFirstFrame = createFromBuffer();
}
- case Disposal::Back:
+ }
+ }
+
+ void createFrame(sal_uInt32 nTarget)
+ {
+ // mnNextFrameToPrepare is the target frame to create next (which implies that
+ // mnNextFrameToPrepare-1 *is* currently in the VirtualDevice when
+ // 0 != mnNextFrameToPrepare. nTarget is the traget frame.
+ if (isValidData())
+ {
+ if (mnNextFrameToPrepare > nTarget)
{
- // #i70772# react on no mask, for primitives, too.
- const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask());
- const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap());
+ // we are ahead request, reset mechanism to start at frame zero
+ ensureVirtualDeviceSizeAndState();
+ mnNextFrameToPrepare = 0;
+ }
- aVirtualDeviceMask->Erase();
- aVirtualDevice->DrawBitmap(rAnimBitmap.aPosPix, aContent);
+ while (mnNextFrameToPrepare <= nTarget)
+ {
+ // prepare step
+ const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare));
- if(aMask.IsEmpty())
+ switch (rAnimBitmap.eDisposal)
{
- const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel());
- aVirtualDeviceMask->SetFillColor(COL_BLACK);
- aVirtualDeviceMask->SetLineColor();
- aVirtualDeviceMask->DrawRect(aRect);
+ case Disposal::Not:
+ {
+ maVirtualDevice->DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
+ Bitmap aMask = rAnimBitmap.aBmpEx.GetMask();
+
+ if (aMask.IsEmpty())
+ {
+ const Point aEmpty;
+ const Rectangle aRect(aEmpty, maVirtualDeviceMask->GetOutputSizePixel());
+ const Wallpaper aWallpaper(COL_BLACK);
+ maVirtualDeviceMask->DrawWallpaper(aRect, aWallpaper);
+ }
+ else
+ {
+ BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask);
+ maVirtualDeviceMask->DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask);
+ }
+
+ break;
+ }
+ case Disposal::Back:
+ {
+ // #i70772# react on no mask, for primitives, too.
+ const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask());
+ const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap());
+
+ maVirtualDeviceMask->Erase();
+ maVirtualDevice->DrawBitmap(rAnimBitmap.aPosPix, aContent);
+
+ if (aMask.IsEmpty())
+ {
+ const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel());
+ maVirtualDeviceMask->SetFillColor(COL_BLACK);
+ maVirtualDeviceMask->SetLineColor();
+ maVirtualDeviceMask->DrawRect(aRect);
+ }
+ else
+ {
+ maVirtualDeviceMask->DrawBitmap(rAnimBitmap.aPosPix, aMask);
+ }
+
+ break;
+ }
+ case Disposal::Previous:
+ {
+ maVirtualDevice->DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
+ maVirtualDeviceMask->DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask());
+ break;
+ }
}
- else
+
+ // to not waste created data, check adding to buffers
+ checkSafeToBuffer(mnNextFrameToPrepare);
+
+ mnNextFrameToPrepare++;
+ }
+ }
+ }
+
+ Primitive2DReference tryTogetFromBuffer(sal_uInt32 nIndex) const
+ {
+ if (mbBufferingAllowed)
+ {
+ // all frames buffered, check if available
+ if (maBufferedPrimitives.size() && nIndex < maBufferedPrimitives.size())
+ {
+ if (maBufferedPrimitives[nIndex].is())
{
- aVirtualDeviceMask->DrawBitmap(rAnimBitmap.aPosPix, aMask);
+ return maBufferedPrimitives[nIndex];
}
-
- break;
}
- case Disposal::Previous :
+ }
+ else
+ {
+ // always buffer first frame, it's sometimes requested out-of-order
+ if (0 == nIndex && maBufferedFirstFrame.is())
{
- aVirtualDevice->DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
- aVirtualDeviceMask->DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask());
- break;
+ return maBufferedFirstFrame;
}
}
- // create BitmapEx
- Bitmap aMainBitmap = aVirtualDevice->GetBitmap(Point(), aVirtualDevice->GetOutputSizePixel());
-#if defined(MACOSX) || defined(IOS)
- AlphaMask aMaskBitmap( aVirtualDeviceMask->GetBitmap( Point(), aVirtualDeviceMask->GetOutputSizePixel()));
-#else
- Bitmap aMaskBitmap = aVirtualDeviceMask->GetBitmap( Point(), aVirtualDeviceMask->GetOutputSizePixel());
-#endif
- aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap);
+ return Primitive2DReference();
+ }
+
+ public:
+ /// constructor
+ AnimatedGraphicPrimitive2D(
+ const Graphic& rGraphic,
+ const basegfx::B2DHomMatrix& rTransform);
+
+ /// data read access
+ const Graphic& getGraphic() const { return maGraphic; }
+ const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
+
+ /// compare operator
+ virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
- // add to vector
- maSteps.push_back(aNextStep);
+ /// override to deliver the correct expected frame dependent of timing
+ virtual Primitive2DContainer get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
+ };
+
+ AnimatedGraphicPrimitive2D::AnimatedGraphicPrimitive2D(
+ const Graphic& rGraphic,
+ const basegfx::B2DHomMatrix& rTransform)
+ : AnimatedSwitchPrimitive2D(
+ animation::AnimationEntryList(),
+ Primitive2DContainer(),
+ false),
+ maTransform(rTransform),
+ maGraphic(rGraphic),
+ maAnimation(rGraphic.GetAnimation()),
+ maVirtualDevice(*Application::GetDefaultDevice()),
+ maVirtualDeviceMask(*Application::GetDefaultDevice(), DeviceFormat::BITMASK),
+ mnNextFrameToPrepare(SAL_MAX_UINT32),
+ maBufferedFirstFrame(),
+ maBufferedPrimitives(),
+ mbBufferingAllowed(false),
+ mbHugeSize(false)
+ {
+ // initialize AnimationTiming, needed to detect which frame is requested
+ // in get2DDecomposition
+ createAndSetAnimationTiming();
+
+ // check if we allow buffering
+ if (isValidData())
+ {
+ // allow buffering up to a size of:
+ // - 64 frames
+ // - sizes of 256x256 pixels
+ // This may be offered in option values if needed
+ static const sal_uInt64 nAllowedSize(64 * 256 * 256);
+ static const sal_uInt64 nHugeSize(10000000);
+ const Size aTarget(maAnimation.GetDisplaySizePixel());
+ const sal_uInt64 nUsedSize((sal_uInt64)maAnimation.Count() * aTarget.Width() * aTarget.Height());
+
+ if (nUsedSize < nAllowedSize)
+ {
+ mbBufferingAllowed = true;
+ }
+
+ if (nUsedSize > nHugeSize)
+ {
+ mbHugeSize = true;
+ }
+ }
+
+ // prepare buffer space
+ if (mbBufferingAllowed && isValidData())
+ {
+ maBufferedPrimitives = Primitive2DContainer(maAnimation.Count());
}
}
- }
-} // end of anonymous namespace
+
+ bool AnimatedGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ // do not use 'GroupPrimitive2D::operator==' here, that would compare
+ // the children. Also do not use 'BasePrimitive2D::operator==', that would
+ // check the ID-Type. Since we are a simple derivation without own ID,
+ // use the dynamic_cast RTTI directly
+ const AnimatedGraphicPrimitive2D* pCompare = dynamic_cast<const AnimatedGraphicPrimitive2D*>(&rPrimitive);
+
+ // use operator== of Graphic - if that is equal, the basic definition is equal
+ return (nullptr != pCompare
+ && getTransform() == pCompare->getTransform()
+ && getGraphic() == pCompare->getGraphic());
+ }
+
+ Primitive2DContainer AnimatedGraphicPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ if (isValidData())
+ {
+ Primitive2DContainer aRetval(1);
+ const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime()));
+ const sal_uInt32 nLen(maAnimation.Count());
+ sal_uInt32 nIndex(basegfx::fround(fState * (double)nLen));
+
+ // nIndex is the requested frame - it is in range [0..nLen[
+ // create frame representation in VirtualDevices
+ if (nIndex >= nLen)
+ {
+ nIndex = nLen - 1L;
+ }
+
+ // check buffering shortcuts, may already be created
+ aRetval[0] = tryTogetFromBuffer(nIndex);
+
+ if (aRetval[0].is())
+ {
+ return aRetval;
+ }
+
+ // if huge size (and not the buffered 1st frame) simply
+ // create next frame
+ if (mbHugeSize && 0 != nIndex && mnNextFrameToPrepare <= nIndex)
+ {
+ nIndex = mnNextFrameToPrepare % nLen;
+ }
+
+ // frame not (yet) buffered or no buffering allowed, create it
+ const_cast<AnimatedGraphicPrimitive2D*>(this)->createFrame(nIndex);
+
+ // try to get from buffer again, may have been added from createFrame
+ aRetval[0] = tryTogetFromBuffer(nIndex);
+
+ if (aRetval[0].is())
+ {
+ return aRetval;
+ }
+
+ // did not work (not buffered and not 1st frame), create from buffer
+ aRetval[0] = createFromBuffer();
+
+ return aRetval;
+ }
+
+ return Primitive2DContainer();
+ }
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
namespace drawinglayer
{
@@ -200,35 +462,11 @@ namespace drawinglayer
{
if(rGraphic.IsAnimated())
{
- // prepare animation data
- animatedBitmapExPreparator aData(rGraphic);
-
- if(aData.count())
- {
- // create sub-primitives for animated bitmap and the needed animation loop
- animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff);
- Primitive2DContainer aBitmapPrimitives(aData.count());
-
- for(sal_uInt32 a(0); a < aData.count(); a++)
- {
- animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count());
- aAnimationLoop.append(aTime);
- aBitmapPrimitives[a] = new BitmapPrimitive2D(
- aData.stepBitmapEx(a),
- rTransform);
- }
-
- // prepare animation list
- animation::AnimationEntryList aAnimationList;
- aAnimationList.append(aAnimationLoop);
-
- // create and add animated switch primitive
- aRetval.resize(1);
- aRetval[0] = new AnimatedSwitchPrimitive2D(
- aAnimationList,
- aBitmapPrimitives,
- false);
- }
+ // prepare specialized AnimatedGraphicPrimitive2D
+ aRetval.resize(1);
+ aRetval[0] = new AnimatedGraphicPrimitive2D(
+ rGraphic,
+ rTransform);
}
else if(rGraphic.getSvgData().get())
{
diff --git a/include/drawinglayer/primitive2d/animatedprimitive2d.hxx b/include/drawinglayer/primitive2d/animatedprimitive2d.hxx
index 7050cbbd33e7..f0cd6e89dcad 100644
--- a/include/drawinglayer/primitive2d/animatedprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/animatedprimitive2d.hxx
@@ -66,6 +66,15 @@ namespace drawinglayer
*/
bool mbIsTextAnimation : 1;
+ protected:
+ /** write access right for classes deriving from this who want to do special
+ things (e.g. optimization, buffering).
+ Caution: This is an exception from the read-only, non-modifyable paradigm
+ for primitives, so special preparations may be needed. Usually should
+ only be used for initialization (e.g. in a derived constructor)
+ */
+ void setAnimationEntry(const animation::AnimationEntry& rNew);
+
public:
/// constructor
AnimatedSwitchPrimitive2D(