slideshow/source/engine/shapes/drawshape.cxx     |   62 +++++
 slideshow/source/engine/shapes/drawshape.hxx     |   37 +++
 slideshow/source/engine/shapes/gdimtftools.cxx   |  248 ++++++++++++-----------
 slideshow/source/engine/shapes/gdimtftools.hxx   |   24 ++
 slideshow/source/engine/shapes/shapeimporter.cxx |    7 
 5 files changed, 251 insertions(+), 127 deletions(-)

New commits:
commit 89998a744f9ee8efa40c0e1cb7bdbc783d3414fa
Author:     Attila Szűcs <attila.sz...@collabora.com>
AuthorDate: Thu Apr 25 01:43:05 2024 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Apr 25 14:05:13 2024 +0200

    tdf#153162 Animation load optimization
    
    Loading a big GIF animation can freeze LO for a long time, so:
    
    changed getAnimationFromGraphic, it can load parts of a big animation.
    It can be called several times to load the whole animation.
    Now it can load animation while it is playing.
    
    It may still load smaller animations at once before it is rendered.
    At first it load frames that sum maximum 5 million pixels.
    (But minimum 10 frame.)
    
    Changed the Graphic parameter to shared_ptr, so it won’t be deleted
    until the whole animation is loaded.
    
    Change-Id: I5ac16d7ee4883dbaefb604cd07757d19e5aa2939
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166608
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/slideshow/source/engine/shapes/drawshape.cxx 
b/slideshow/source/engine/shapes/drawshape.cxx
index 185b76cc23d3..de89822dac58 100644
--- a/slideshow/source/engine/shapes/drawshape.cxx
+++ b/slideshow/source/engine/shapes/drawshape.cxx
@@ -343,6 +343,7 @@ namespace slideshow::internal
             mxPage( xContainingPage ),
             maAnimationFrames(), // empty, we don't have no intrinsic animation
             mnCurrFrame(0),
+            mpGraphicLoader(),
             mpCurrMtf(),
             mnCurrMtfLoadFlags( bForeignSource
                                 ? MTF_LOAD_FOREIGN_SOURCE : MTF_LOAD_NONE ),
@@ -418,12 +419,13 @@ namespace slideshow::internal
         DrawShape::DrawShape( const uno::Reference< drawing::XShape >&      
xShape,
                               uno::Reference< drawing::XDrawPage > 
xContainingPage,
                               double                                        
nPrio,
-                              const Graphic&                                
rGraphic,
+                              std::shared_ptr<Graphic>                      
pGraphic,
                               const SlideShowContext&                       
rContext ) :
             mxShape( xShape ),
             mxPage(std::move( xContainingPage )),
             maAnimationFrames(),
             mnCurrFrame(0),
+            mpGraphicLoader(),
             mpCurrMtf(),
             mnCurrMtfLoadFlags( MTF_LOAD_NONE ),
             maCurrentShapeUnitBounds(),
@@ -450,12 +452,25 @@ namespace slideshow::internal
             mbDrawingLayerAnim( false ),
             mbContainsPageField( false )
         {
-            ENSURE_OR_THROW( rGraphic.IsAnimated(),
+            ENSURE_OR_THROW( pGraphic->IsAnimated(),
                               "DrawShape::DrawShape(): Graphic is no 
animation" );
 
-            getAnimationFromGraphic( maAnimationFrames,
-                                     mnAnimationLoopCount,
-                                     rGraphic );
+            ::Animation aAnimation(pGraphic->GetAnimation());
+            const Size aAnimSize(aAnimation.GetDisplaySizePixel());
+            tools::Long nBitmapPixels = aAnimSize.getWidth() * 
aAnimSize.getHeight();
+
+            tools::Long nFramesToLoad = aAnimation.Count();
+
+            // if the Animation is bigger then 5 million pixels, we do not 
load the
+            // whole animation now.
+            if (nBitmapPixels * aAnimation.Count() > 5000000)
+            {
+                nFramesToLoad = 5000000 / nBitmapPixels;
+                if (nFramesToLoad < 10)
+                    nFramesToLoad = 10;
+            }
+            mpGraphicLoader = 
::std::make_unique<DelayedGraphicLoader>(pGraphic);
+            getSomeAnimationFramesFromGraphic(nFramesToLoad);
 
             ENSURE_OR_THROW( !maAnimationFrames.empty() &&
                               maAnimationFrames.front().mpMtf,
@@ -475,6 +490,7 @@ namespace slideshow::internal
             maAnimationFrames(), // don't copy animations for subsets,
                                  // only the current frame!
             mnCurrFrame(0),
+            mpGraphicLoader(),
             mpCurrMtf( rSrc.mpCurrMtf ),
             mnCurrMtfLoadFlags( rSrc.mnCurrMtfLoadFlags ),
             maCurrentShapeUnitBounds(),
@@ -550,13 +566,13 @@ namespace slideshow::internal
             const uno::Reference< drawing::XShape >&    xShape,
             const uno::Reference< drawing::XDrawPage >& xContainingPage,
             double                                      nPrio,
-            const Graphic&                              rGraphic,
+            std::shared_ptr<Graphic>                    pGraphic,
             const SlideShowContext&                     rContext )
         {
             DrawShapeSharedPtr pShape( new DrawShape(xShape,
                                                      xContainingPage,
                                                      nPrio,
-                                                     rGraphic,
+                                                     pGraphic,
                                                      rContext) );
 
             if( pShape->hasIntrinsicAnimation() )
@@ -847,6 +863,10 @@ namespace slideshow::internal
             ENSURE_OR_RETURN_VOID( nCurrFrame < maAnimationFrames.size(),
                                "DrawShape::setIntrinsicAnimationFrame(): frame 
index out of bounds" );
 
+            // Load 1 more frame if needed. (make sure the current frame is 
loded)
+            if (mpGraphicLoader)
+                getSomeAnimationFramesFromGraphic(1, nCurrFrame);
+
             if( mnCurrFrame != nCurrFrame )
             {
                 mnCurrFrame   = nCurrFrame;
@@ -1235,6 +1255,34 @@ namespace slideshow::internal
         {
             return maSubsetting.getSubsetTreeNode( rParentNode, nNodeIndex, 
eNodeType );
         }
+
+        void DrawShape::getSomeAnimationFramesFromGraphic(::std::size_t 
nFrameCount,
+                                                          ::std::size_t 
nLastToLoad /* = 0*/)
+        {
+            OSL_ASSERT(mpGraphicLoader);
+
+            //load nFrameCount frames or to nLastToLoad
+            ::std::size_t nFramesToLoad = nFrameCount;
+            if (nLastToLoad > mpGraphicLoader->mnLoadedFrames + nFrameCount)
+                nFramesToLoad = nLastToLoad - mpGraphicLoader->mnLoadedFrames;
+
+            getAnimationFromGraphic(maAnimationFrames, mnAnimationLoopCount,
+                                    mpGraphicLoader->mpGraphic, 
mpGraphicLoader->mpVDev,
+                                    mpGraphicLoader->mpVDevMask, 
mpGraphicLoader->mnLoadedFrames,
+                                    nFramesToLoad);
+
+            // If the Animation is fully loaded, no need to load anymore.
+            if (mpGraphicLoader->mnLoadedFrames >= maAnimationFrames.size())
+            {
+                mpGraphicLoader.reset();
+            }
+        }
+
+        DelayedGraphicLoader::DelayedGraphicLoader(std::shared_ptr<Graphic> 
pGraphic)
+            : mpGraphic(pGraphic)
+            , mpVDevMask(DeviceFormat::WITHOUT_ALPHA)
+        {
+        }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/slideshow/source/engine/shapes/drawshape.hxx 
b/slideshow/source/engine/shapes/drawshape.hxx
index 6c71d151b6fa..efa55299f435 100644
--- a/slideshow/source/engine/shapes/drawshape.hxx
+++ b/slideshow/source/engine/shapes/drawshape.hxx
@@ -30,6 +30,8 @@
 #include "viewshape.hxx"
 #include <hyperlinkarea.hxx>
 
+#include <vcl/virdev.hxx>
+
 #include <optional>
 #include <vector>
 
@@ -43,6 +45,22 @@ namespace slideshow::internal
         class  DrawShape;
         typedef ::std::shared_ptr< DrawShape > DrawShapeSharedPtr;
 
+        /** This Struct store data needed to make Animation from Graphic.
+            If the Animation is too big, we won't load all of it at once.
+            From time to time we load small parts until it is completely 
loaded.
+            Because of it, we have to keep some data alive until the animation
+            is fully loaded.
+         */
+        struct DelayedGraphicLoader
+        {
+            sal_uInt16 mnLoadedFrames = 0;
+            ::std::shared_ptr<Graphic> mpGraphic;
+            ScopedVclPtrInstance<VirtualDevice> mpVDev;
+            ScopedVclPtrInstance<VirtualDevice> mpVDevMask;
+
+            DelayedGraphicLoader(std::shared_ptr<Graphic> pGraphic);
+        };
+
         /** This class is the representation of a draw document's
             XShape, and implements the Shape, AnimatableShape, and
             AttributableShape interfaces.
@@ -107,7 +125,8 @@ namespace slideshow::internal
                 const css::uno::Reference< css::drawing::XShape >&    xShape,
                 const css::uno::Reference< css::drawing::XDrawPage >& 
xContainingPage,
                 double                                     nPrio,
-                const Graphic&                             rGraphic,
+                std::shared_ptr<Graphic>                   pGraphic,
+
                 const SlideShowContext&                    rContext ); // 
throw ShapeLoadFailedException;
 
             virtual css::uno::Reference< css::drawing::XShape > getXShape() 
const override;
@@ -199,6 +218,19 @@ namespace slideshow::internal
             */
             GDIMetaFileSharedPtr const & forceScrollTextMetaFile();
 
+            /** extract some Animation Frames from the Graphic
+                set in DelayedGraphicLoader.
+
+                @param nFrameCount
+                Load this many frames.
+
+                @param nLastToLoad
+                If nLastToLoad > nFrameCount + loadedFrames then
+                Load frames until this frame.
+             */
+            void getSomeAnimationFramesFromGraphic(::std::size_t nFrameCount,
+                                                   ::std::size_t nLastToLoad = 
0);
+
         private:
             /** Create a shape for the given XShape
 
@@ -251,7 +283,7 @@ namespace slideshow::internal
             DrawShape( const css::uno::Reference< css::drawing::XShape >&    
xShape,
                        css::uno::Reference< css::drawing::XDrawPage > 
xContainingPage,
                        double                                       nPrio,
-                       const Graphic&                               rGraphic,
+                       std::shared_ptr<Graphic>                     pGraphic,
                        const SlideShowContext&                      rContext 
); // throw ShapeLoadFailedException;
 
             /** Private copy constructor
@@ -282,6 +314,7 @@ namespace slideshow::internal
              */
             mutable VectorOfMtfAnimationFrames                                 
     maAnimationFrames;
             ::std::size_t                                                      
     mnCurrFrame;
+            ::std::unique_ptr<DelayedGraphicLoader>                            
     mpGraphicLoader; //to load more Frames later
 
             /// Metafile of currently active frame (static for shapes w/o 
intrinsic animation)
             mutable GDIMetaFileSharedPtr                                       
     mpCurrMtf;
diff --git a/slideshow/source/engine/shapes/gdimtftools.cxx 
b/slideshow/source/engine/shapes/gdimtftools.cxx
index 0ca2673daa5f..d4f55928562f 100644
--- a/slideshow/source/engine/shapes/gdimtftools.cxx
+++ b/slideshow/source/engine/shapes/gdimtftools.cxx
@@ -248,101 +248,119 @@ sal_Int32 getNextActionOffset( MetaAction * pCurrAct )
 
 bool getAnimationFromGraphic( VectorOfMtfAnimationFrames&   o_rFrames,
                               sal_uInt32&                   o_rLoopCount,
-                              const Graphic&                rGraphic )
+                              std::shared_ptr<Graphic>      pGraphic,
+                              ScopedVclPtrInstance<VirtualDevice>& pVDev,
+                              ScopedVclPtrInstance<VirtualDevice>& pVDevMask,
+                              sal_uInt16&                   mnLoadedFrames,
+                              sal_uInt16                    nFramesToLoad )
 {
-    o_rFrames.clear();
+    bool bFirstRun = mnLoadedFrames == 0;
+    if (bFirstRun)
+        o_rFrames.clear();
 
-    if( !rGraphic.IsAnimated() )
+    if( !pGraphic->IsAnimated() )
         return false;
 
     // some loop invariants
-    ::Animation   aAnimation( rGraphic.GetAnimation() );
+    ::Animation   aAnimation( pGraphic->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)
-    ScopedVclPtrInstance< VirtualDevice > pVDev;
-    pVDev->SetOutputSizePixel( aAnimSize );
-    pVDev->EnableMapMode( false );
-
-    // setup mask VDev (alpha VDev is currently rather slow)
-    ScopedVclPtrInstance<VirtualDevice> pVDevMask(DeviceFormat::WITHOUT_ALPHA);
-    pVDevMask->SetOutputSizePixel( aAnimSize );
-    pVDevMask->EnableMapMode( false );
-
-    // tdf#156630 make erase calls fill with transparency
-    pVDev->SetBackground( Wallpaper( COL_BLACK ) );
-    pVDevMask->SetBackground( Wallpaper( COL_ALPHA_TRANSPARENT ) );
-
-    o_rLoopCount = aAnimation.GetLoopCount();
-
-    for( sal_uInt16 i=0, nCount=aAnimation.Count(); i<nCount; ++i )
+    if (bFirstRun)
+    {
+        // 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)
+        pVDev->SetOutputSizePixel(aAnimSize);
+        pVDev->EnableMapMode(false);
+
+        // setup mask VDev (alpha VDev is currently rather slow)
+        pVDevMask->SetOutputSizePixel(aAnimSize);
+        pVDevMask->EnableMapMode(false);
+
+        // tdf#156630 make erase calls fill with transparency
+        pVDev->SetBackground(Wallpaper(COL_BLACK));
+        pVDevMask->SetBackground(Wallpaper(COL_ALPHA_TRANSPARENT));
+
+        o_rLoopCount = aAnimation.GetLoopCount();
+    }
+    sal_uInt16 nCount = aAnimation.Count();
+    if (!bFirstRun && mnLoadedFrames + nFramesToLoad < nCount)
+        nCount = mnLoadedFrames + nFramesToLoad;
+    for (sal_uInt16 i = mnLoadedFrames; i < nCount; ++i)
     {
         const AnimationFrame& rAnimationFrame( aAnimation.Get(i) );
-        switch(rAnimationFrame.meDisposal)
+        bool bCalculateNow = !bFirstRun || i < nFramesToLoad;
+        if (bCalculateNow)
         {
-            case Disposal::Not:
+            switch (rAnimationFrame.meDisposal)
             {
-                pVDev->DrawBitmapEx(rAnimationFrame.maPositionPixel,
-                                    rAnimationFrame.maBitmapEx);
-                AlphaMask aMask = rAnimationFrame.maBitmapEx.GetAlphaMask();
-
-                if( aMask.IsEmpty() )
+                case Disposal::Not:
                 {
-                    const tools::Rectangle aRect(aEmptyPoint,
-                                          pVDevMask->GetOutputSizePixel());
-                    const Wallpaper aWallpaper(COL_BLACK);
-                    pVDevMask->DrawWallpaper(aRect,
-                                            aWallpaper);
-                }
-                else
-                {
-                    BitmapEx aTmpMask(aMask.GetBitmap(), aMask);
-                    pVDevMask->DrawBitmapEx(rAnimationFrame.maPositionPixel,
-                                            aTmpMask );
+                    pVDev->DrawBitmapEx(rAnimationFrame.maPositionPixel,
+                                        rAnimationFrame.maBitmapEx);
+                    AlphaMask aMask = 
rAnimationFrame.maBitmapEx.GetAlphaMask();
+
+                    if (aMask.IsEmpty())
+                    {
+                        const tools::Rectangle aRect(aEmptyPoint, 
pVDevMask->GetOutputSizePixel());
+                        const Wallpaper aWallpaper(COL_BLACK);
+                        pVDevMask->DrawWallpaper(aRect, aWallpaper);
+                    }
+                    else
+                    {
+                        BitmapEx aTmpMask(aMask.GetBitmap(), aMask);
+                        
pVDevMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aTmpMask);
+                    }
+                    break;
                 }
-                break;
-            }
-
-            case Disposal::Back:
-            {
-                // #i70772# react on no mask
-                const AlphaMask 
aMask(rAnimationFrame.maBitmapEx.GetAlphaMask());
-                const Bitmap & 
rContent(rAnimationFrame.maBitmapEx.GetBitmap());
 
-                pVDevMask->Erase();
-                pVDev->DrawBitmap(rAnimationFrame.maPositionPixel, rContent);
-
-                if(aMask.IsEmpty())
+                case Disposal::Back:
                 {
-                    const tools::Rectangle 
aRect(rAnimationFrame.maPositionPixel, rContent.GetSizePixel());
-                    pVDevMask->SetFillColor( COL_BLACK);
-                    pVDevMask->SetLineColor();
-                    pVDevMask->DrawRect(aRect);
+                    // #i70772# react on no mask
+                    const AlphaMask 
aMask(rAnimationFrame.maBitmapEx.GetAlphaMask());
+                    const Bitmap& 
rContent(rAnimationFrame.maBitmapEx.GetBitmap());
+
+                    pVDevMask->Erase();
+                    pVDev->DrawBitmap(rAnimationFrame.maPositionPixel, 
rContent);
+
+                    if (aMask.IsEmpty())
+                    {
+                        const tools::Rectangle 
aRect(rAnimationFrame.maPositionPixel,
+                                                     rContent.GetSizePixel());
+                        pVDevMask->SetFillColor(COL_BLACK);
+                        pVDevMask->SetLineColor();
+                        pVDevMask->DrawRect(aRect);
+                    }
+                    else
+                    {
+                        pVDevMask->DrawBitmap(rAnimationFrame.maPositionPixel, 
aMask.GetBitmap());
+                    }
+                    break;
                 }
-                else
+
+                case Disposal::Previous:
                 {
-                    pVDevMask->DrawBitmap(rAnimationFrame.maPositionPixel, 
aMask.GetBitmap());
+                    pVDev->DrawBitmapEx(rAnimationFrame.maPositionPixel,
+                                        rAnimationFrame.maBitmapEx);
+                    pVDevMask->DrawBitmap(rAnimationFrame.maPositionPixel,
+                                          
rAnimationFrame.maBitmapEx.GetAlphaMask().GetBitmap());
+                    break;
                 }
-                break;
-            }
-
-            case Disposal::Previous :
-            {
-                pVDev->DrawBitmapEx(rAnimationFrame.maPositionPixel,
-                                    rAnimationFrame.maBitmapEx);
-                pVDevMask->DrawBitmap(rAnimationFrame.maPositionPixel,
-                                      
rAnimationFrame.maBitmapEx.GetAlphaMask().GetBitmap());
-                break;
             }
         }
-
         // extract current aVDev content into a new animation
         // frame
-        GDIMetaFileSharedPtr pMtf = std::make_shared<GDIMetaFile>();
+        GDIMetaFileSharedPtr pMtf;
+        if (bFirstRun)
+        {
+            pMtf = std::make_shared<GDIMetaFile>();
+        }
+        else
+        {
+            pMtf = o_rFrames[i].mpMtf;
+        }
         bool useAlphaMask = false;
 #if defined(MACOSX) || defined(IOS)
         useAlphaMask = true;
@@ -351,52 +369,58 @@ bool getAnimationFromGraphic( VectorOfMtfAnimationFrames& 
  o_rFrames,
         if( SkiaHelper::isVCLSkiaEnabled())
             useAlphaMask = true;
 #endif
-        if( useAlphaMask )
+        if (bCalculateNow)
         {
-            AlphaMask aAlphaMask(pVDevMask->GetBitmap(aEmptyPoint, aAnimSize));
-            pMtf->AddAction(
-                new MetaBmpExAction( aEmptyPoint,
-                                     BitmapEx(
-                                         pVDev->GetBitmap(
-                                             aEmptyPoint,
-                                             aAnimSize ),
-                                         aAlphaMask)));
+            if( useAlphaMask )
+            {
+                AlphaMask aAlphaMask(pVDevMask->GetBitmap(aEmptyPoint, 
aAnimSize));
+                pMtf->AddAction(
+                    new MetaBmpExAction( aEmptyPoint,
+                                         BitmapEx(
+                                             pVDev->GetBitmap(
+                                                 aEmptyPoint,
+                                                 aAnimSize ),
+                                             aAlphaMask)));
+            }
+            else
+            {
+                Bitmap aAlphaMask = pVDevMask->GetBitmap(aEmptyPoint, 
aAnimSize);
+                aAlphaMask.Invert(); // convert from transparency to alpha
+                pMtf->AddAction(
+                    new MetaBmpExAction( aEmptyPoint,
+                                         BitmapEx(
+                                             pVDev->GetBitmap(
+                                                 aEmptyPoint,
+                                                 aAnimSize ),
+                                             aAlphaMask)));
+            }
+            mnLoadedFrames = i+1;
         }
-        else
+        if (bFirstRun)
         {
-            Bitmap aAlphaMask = pVDevMask->GetBitmap(aEmptyPoint, aAnimSize);
-            aAlphaMask.Invert(); // convert from transparency to alpha
-            pMtf->AddAction(
-                new MetaBmpExAction( aEmptyPoint,
-                                     BitmapEx(
-                                         pVDev->GetBitmap(
-                                             aEmptyPoint,
-                                             aAnimSize ),
-                                         aAlphaMask)));
-        }
+            // 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);
+
+            // Take care of special value for MultiPage TIFFs. ATM these shall 
just
+            // show their first page for _quite_ some time.
+            sal_Int32 nWaitTime100thSeconds(rAnimationFrame.mnWait);
+            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;
+            }
 
-        // 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 );
+            // There are animated GIFs with no WaitTime set. Take 0.1 sec, the
+            // same duration that is used by the edit view.
+            if (nWaitTime100thSeconds == 0)
+                nWaitTime100thSeconds = 10;
 
-        // Take care of special value for MultiPage TIFFs. ATM these shall just
-        // show their first page for _quite_ some time.
-        sal_Int32 nWaitTime100thSeconds(rAnimationFrame.mnWait);
-        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;
+            o_rFrames.emplace_back(pMtf, nWaitTime100thSeconds / 100.0);
         }
-
-        // There are animated GIFs with no WaitTime set. Take 0.1 sec, the
-        // same duration that is used by the edit view.
-        if( nWaitTime100thSeconds == 0 )
-            nWaitTime100thSeconds = 10;
-
-        o_rFrames.emplace_back( pMtf, nWaitTime100thSeconds / 100.0 );
     }
 
     return !o_rFrames.empty();
diff --git a/slideshow/source/engine/shapes/gdimtftools.hxx 
b/slideshow/source/engine/shapes/gdimtftools.hxx
index 8395efeb00a2..c23b16ae53c5 100644
--- a/slideshow/source/engine/shapes/gdimtftools.hxx
+++ b/slideshow/source/engine/shapes/gdimtftools.hxx
@@ -27,6 +27,8 @@
 
 #include <basegfx/range/b2drectangle.hxx>
 
+#include <vcl/virdev.hxx>
+
 #include <tools.hxx>
 
 #include <utility>
@@ -101,6 +103,8 @@ namespace slideshow::internal
         sal_Int32 getNextActionOffset( MetaAction * pCurrAct );
 
         /** Extract a vector of animation frames from given Graphic.
+            It can be used to extract only a few frames, and can be
+            called later to extract more. (If the Animation is big)
 
             @param o_rFrames
             Resulting vector of animated metafiles
@@ -108,12 +112,28 @@ namespace slideshow::internal
             @param o_rLoopCount
             Number of times the bitmap animation shall be repeated
 
-            @param rGraphic
+            @param pGraphic
             Input graphic object, to extract animations from
+
+            @param pVDev, pVDevMask
+            Virtual devices. We don't want to create new everytime we load 
some frames.
+
+            @param nLoadedFrames
+            The count of loaded Frames.
+
+            @param nFramesToLoad
+            The count of Frames need to be extracted now.
+            Bigger nFramesToLoad not result an error, the function will
+            stop extracting at the end of the animation anyway.
          */
+
         bool getAnimationFromGraphic(VectorOfMtfAnimationFrames& o_rFrames,
                                      sal_uInt32&                 o_rLoopCount,
-                                     const Graphic&              rGraphic);
+                                     std::shared_ptr<Graphic>    pGraphic,
+                                     ScopedVclPtrInstance<VirtualDevice> 
&pVDev,
+                                     ScopedVclPtrInstance<VirtualDevice> 
&pVDevMask,
+                                     sal_uInt16&                 nLoadedFrames,
+                                     sal_uInt16                  
nFramesToLoad);
 
         /** Retrieve scroll text animation rectangles from given metafile
 
diff --git a/slideshow/source/engine/shapes/shapeimporter.cxx 
b/slideshow/source/engine/shapes/shapeimporter.cxx
index 7823a5588efd..33cb42469d31 100644
--- a/slideshow/source/engine/shapes/shapeimporter.cxx
+++ b/slideshow/source/engine/shapes/shapeimporter.cxx
@@ -311,9 +311,8 @@ ShapeSharedPtr ShapeImporter::createShape(
         // fetch readily transformed and color-modified
         // graphic
 
-
-        Graphic aGraphic(
-            xGraphicObject->GetTransformedGraphic(
+        std::shared_ptr<Graphic> pGraphic
+            = 
::std::make_shared<Graphic>(xGraphicObject->GetTransformedGraphic(
                 xGraphicObject->GetPrefSize(),
                 xGraphicObject->GetPrefMapMode(),
                 aGraphAttrs ) );
@@ -321,7 +320,7 @@ ShapeSharedPtr ShapeImporter::createShape(
         return DrawShape::create( xCurrShape,
                                   mxPage,
                                   mnAscendingPrio,
-                                  aGraphic,
+                                  pGraphic,
                                   mrContext );
     }
     else

Reply via email to