[Libreoffice-commits] core.git: Branch 'libreoffice-5-2' - 2 commits - drawinglayer/source include/drawinglayer sw/source

Caolán McNamara caolanm at redhat.com
Fri Jun 10 14:01:01 UTC 2016


 drawinglayer/source/primitive2d/animatedprimitive2d.cxx      |    9 
 drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx |  516 ++++++++---
 include/drawinglayer/primitive2d/animatedprimitive2d.hxx     |    9 
 sw/source/core/doc/DocumentContentOperationsManager.cxx      |    9 
 4 files changed, 401 insertions(+), 142 deletions(-)

New commits:
commit 61a98b7bb14986f6c7c218effacabbe4b925f6b6
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Jun 10 14:56:54 2016 +0100

    Resolves: tdf#100275 makeMark may return null under some circumstances
    
    Change-Id: If3b83413c028c6cd1c055e632b6f050ec7f2475d
    (cherry picked from commit 5c1a1d1c66aff497702abc20df5832fa348f1008)

diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index eab114b..e5218f4 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -254,9 +254,12 @@ namespace
                 aTmpPam,
                 pMark->GetName(),
                 IDocumentMarkAccess::GetType(*pMark));
-            // Explicitly try to get exactly the same name as in the source
-            // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
-            pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
+            if (pNewMark)
+            {
+                // Explicitly try to get exactly the same name as in the source
+                // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
+                pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
+            }
 
             // copying additional attributes for bookmarks or fieldmarks
             ::sw::mark::IBookmark* const pNewBookmark =
commit 702b58945b51e738cdcc3d383ca38881f9f1338d
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Jun 3 13:58:40 2016 +0200

    tdf#99519 Added more intelligent handling of animated GIFs
    
    Isolated to a single Primitive2D class based on the AnimatedSwitch-
    Primitive2D which does the specializing in one place. Buffers small
    GIFs completely, handles 1st frame always buffered, huge GIFs get
    animated by just playing he next frame.
    To reach more with the current approach we would have to re-implement
    AnimatedGIF import, replay it internally on a sys-specific Surface
    and blit the current content (with alpha) to our display
    
    Reviewed-on: https://gerrit.libreoffice.org/26103
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 285744fef87f4ca0278834b97d7f618bdba5f4c0)
    
    Change-Id: I46c3325fa7936df73bea9a9284a0421f1475a34b

diff --git a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx
index 03712fb..d832a43 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 87d3959..bd62db8 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 7050cbb..f0cd6e8 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(


More information about the Libreoffice-commits mailing list