[Libreoffice-commits] core.git: 3 commits - include/svtools svtools/source sw/source vcl/win

Armin Le Grand alg at apache.org
Tue Jul 15 08:15:51 PDT 2014


 include/svtools/grfmgr.hxx         |   22 ++++++++++
 svtools/source/graphic/grfmgr.cxx  |   50 +++++++++++++++++++-----
 svtools/source/graphic/grfmgr2.cxx |   75 ++++++++++++++++++++++++++++++++++++-
 sw/source/core/doc/notxtfrm.cxx    |   57 +++++++++++++++++++++++++---
 sw/source/core/inc/frmtool.hxx     |    4 -
 sw/source/core/layout/paintfrm.cxx |    2 
 vcl/win/source/gdi/salbmp.cxx      |   54 +++++++++++++++-----------
 7 files changed, 220 insertions(+), 44 deletions(-)

New commits:
commit 8930030323f269a9b3c6bd6a09fc723e09211caa
Author: Armin Le Grand <alg at apache.org>
Date:   Thu Jul 3 13:58:29 2014 +0000

    Resolves: #i125171# support lossless embedding of linked jpegs...
    
    in writer for PDF export
    
    (cherry picked from commit 131669af7168020750b726e4e6d1568975f73886)
    
    Conflicts:
    	sw/source/core/doc/notxtfrm.cxx
    
    Add missing includes to fix build break
    
    (cherry picked from commit 662b23eb1f1b7c178a7a5507864c647a390fae34)
    
    Conflicts:
    	sw/source/core/doc/notxtfrm.cxx
    
    1e2c208ac91c8e666e4f3f6f89cd917736cdc44d
    
    Change-Id: Ie560fa05964b79240fbd97825be74b0543c97aba

diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index 0f98c9c..c6bae4a 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -75,6 +75,8 @@
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <drawinglayer/processor2d/processor2dtools.hxx>
 #include <txtfly.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/pdfextoutdevdata.hxx>
 
 using namespace com::sun::star;
 
@@ -754,7 +756,7 @@ bool paintUsingPrimitivesHelper(
 }
 
 void paintGraphicUsingPrimitivesHelper(OutputDevice & rOutputDevice,
-         Graphic const& rGraphic, GraphicAttr const& rGraphicAttr,
+         GraphicObject const& rGrfObj, GraphicAttr const& rGraphicAttr,
          SwRect const& rAlignedGrfArea)
 {
     // unify using GraphicPrimitive2D
@@ -768,12 +770,55 @@ void paintGraphicUsingPrimitivesHelper(OutputDevice & rOutputDevice,
         basegfx::tools::createScaleTranslateB2DHomMatrix(
             aTargetRange.getRange(),
             aTargetRange.getMinimum()));
+
     drawinglayer::primitive2d::Primitive2DSequence aContent(1);
+    bool bDone(false);
+
+    // #i125171# The mechanism to get lossless jpegs into pdf is based on having the original
+    // file data (not the bitmap data) at the Graphic in the GfxLink (which has *nothing* to
+    // do with the graphic being linked). This works well for DrawingLayer GraphicObjects (linked
+    // and unlinked) but fails for linked Writer GraphicObjects. These have the URL in the
+    // GraphicObject, but no GfxLink with the original file data when it's a linked graphic.
+    // Since this blows up PDF size by a factor of 10 (the graphics get embedded as pixel maps
+    // then) it is okay to add this workarund: In the needed case, load the graphic in a way to
+    // get the GfxLink in the needed form and use that Graphic temporarily. Do this only when
+    // - we have PDF export
+    // - the GraphicObject is linked
+    // - the Graphic has no GfxLink
+    // - LosslessCompression is activated
+    // - it's indeed a jpeg graphic (could be checked by the url ending, but is more reliable to check later)
+    // In all other cases (normal repaint, print, etc...) use the available Graphic with the
+    // already loaded pixel graphic as before this change.
+    if (rOutputDevice.GetExtOutDevData() && rGrfObj.HasLink() && !rGrfObj.GetGraphic().IsLink())
+    {
+        const vcl::PDFExtOutDevData* pPDFExt = dynamic_cast< const vcl::PDFExtOutDevData* >(rOutputDevice.GetExtOutDevData());
+
+        if (pPDFExt && pPDFExt->GetIsLosslessCompression())
+        {
+            Graphic aTempGraphic;
+            INetURLObject aURL(rGrfObj.GetLink());
 
-    aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D(
-        aTargetTransform,
-        rGraphic,
-        rGraphicAttr);
+            if (GRFILTER_OK == GraphicFilter::GetGraphicFilter().ImportGraphic(aTempGraphic, aURL))
+            {
+                if(aTempGraphic.IsLink() && GFX_LINK_TYPE_NATIVE_JPG == aTempGraphic.GetLink().GetType())
+                {
+                    aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D(
+                        aTargetTransform,
+                        aTempGraphic,
+                        rGraphicAttr);
+                    bDone = true;
+                }
+            }
+        }
+    }
+
+    if(!bDone)
+    {
+        aContent[0] = new drawinglayer::primitive2d::GraphicPrimitive2D(
+            aTargetTransform,
+            rGrfObj.GetGraphic(),
+            rGraphicAttr);
+    }
 
     paintUsingPrimitivesHelper(
         rOutputDevice,
@@ -905,7 +950,7 @@ void SwNoTxtFrm::PaintPicture( OutputDevice* pOut, const SwRect &rGrfArea ) cons
                 else
                 {
                     paintGraphicUsingPrimitivesHelper(*pOut,
-                            rGrfObj.GetGraphic(), aGrfAttr, aAlignedGrfArea);
+                            rGrfObj, aGrfAttr, aAlignedGrfArea);
                 }
             }
             else
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
index 1372efb..1fdaee5 100644
--- a/sw/source/core/inc/frmtool.hxx
+++ b/sw/source/core/inc/frmtool.hxx
@@ -40,7 +40,7 @@ class XFillGradientItem;
 class SdrMarkList;
 class SwNodeIndex;
 class OutputDevice;
-class Graphic;
+class GraphicObject;
 class GraphicAttr;
 class SwPageDesc;
 class SwFrmFmts;
@@ -72,7 +72,7 @@ bool DrawFillAttributes(
 
 void paintGraphicUsingPrimitivesHelper(
         OutputDevice & rOutputDevice,
-        Graphic const& rGraphic, GraphicAttr const& rGraphicAttr,
+        GraphicObject const& rGraphicObj, GraphicAttr const& rGraphicAttr,
         SwRect const& rAlignedGrfArea);
 
 // method to align rectangle.
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 162c7a9..f3aad5f 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -1817,7 +1817,7 @@ static void lcl_DrawGraphic( const SvxBrushItem& rBrush, OutputDevice *pOut,
     if (pGrf->GetGraphic().getSvgData().get())
     {   // fdo#68927 - SVGs are rasterized badly by DrawWithPDFHandling
         paintGraphicUsingPrimitivesHelper(*pOut,
-                pGrf->GetGraphic(), pGrf->GetAttr(), aAlignedGrfRect);
+                *pGrf, pGrf->GetAttr(), aAlignedGrfRect);
     }
     else
     {
commit 60de576a295682002c59b90b1429da25bcd854ea
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Tue Jul 15 12:58:17 2014 +0100

    use same swap stategy on all platforms
    
    Change-Id: I565dfd9233088feae69de6261d1081fc51f10806

diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index d5731d8..3db6161 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -189,60 +189,56 @@ namespace
 
 void GraphicManager::ImplCheckSizeOfSwappedInGraphics()
 {
-    // only necessary for 32bit systems
-    if(SAL_TYPES_SIZEOFPOINTER <= 4)
+    // get the currently used memory footprint of all swapped in bitmap graphics
+    // of this graphic manager. Remember candidates in a vector. The size in bytes is
+    // already available, thus this loop is not expensive to execute
+    sal_uLong nUsedSize(0);
+    GraphicObject* pObj = 0;
+    std::vector< GraphicObject* > aCandidates;
+
+    for (size_t i = 0, n = maObjList.size(); i < n; ++i)
     {
-        // get the currently used memory footprint of all swapped in bitmap graphics
-        // of this graphic manager. Remember candidates in a vector. The size in bytes is
-        // already available, thus this loop is not expensive to execute
-        sal_uLong nUsedSize(0);
-        GraphicObject* pObj = 0;
-        std::vector< GraphicObject* > aCandidates;
-
-        for (size_t i = 0, n = maObjList.size(); i < n; ++i)
+        pObj = maObjList[i];
+        if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes())
         {
-            pObj = maObjList[i];
-            if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes())
-            {
-                aCandidates.push_back(pObj);
-                nUsedSize += pObj->GetSizeBytes();
-            }
+            aCandidates.push_back(pObj);
+            nUsedSize += pObj->GetSizeBytes();
         }
+    }
+
+    // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted
+    // to 20MB) and add a decent multiplicator (experimented to find one). Limit to
+    // a useful maximum for 32Bit address space
 
-        // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted
-        // to 20MB) and add a decent multiplicator (expecrimented to find one). Limit to
-        // a useful maximum for 32Bit address space
+    // default is 20MB, so allow 200MB initially
+    static sal_uLong aMultiplicator(10);
 
-        // default is 20MB, so allow 200MB initially
-        static sal_uLong aMultiplicator(10);
+    // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start
+    // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for
+    // app activity is needed
+    static sal_uLong aMaxSize32Bit(500 * 1024 * 1024);
 
-        // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start
-        // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for
-        // app activity is needed
-        static sal_uLong aMaxSize32Bit(500 * 1024 * 1024);
+    // calc max allowed cache size
+    const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit));
 
-        // calc max allowed cache size
-        const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit));
+    if(nUsedSize >= nMaxCacheSize && !aCandidates.empty())
+    {
+        // if we use more currently, sort by last DataChangeTimeStamp
+        // sort by DataChangeTimeStamp so that the oldest get removed first
+        ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp());
 
-        if(nUsedSize >= nMaxCacheSize && !aCandidates.empty())
+        for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++)
         {
-            // if we use more currently, sort by last DataChangeTimeStamp
-            // sort by DataChangeTimeStamp so that the oldest get removed first
-            ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp());
+            // swap out until we have no more or the goal to use less than nMaxCacheSize
+            // is reached
+            pObj = aCandidates[a];
+            const sal_uLong nSizeBytes(pObj->GetSizeBytes());
 
-            for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++)
+            // do not swap out when we have less than 16KB data objects
+            if(nSizeBytes >= (16 * 1024))
             {
-                // swap out until we have no more or the goal to use less than nMaxCacheSize
-                // is reached
-                pObj = aCandidates[a];
-                const sal_uLong nSizeBytes(pObj->GetSizeBytes());
-
-                // do not swap out when we have less than 16KB data objects
-                if(nSizeBytes >= (16 * 1024))
-                {
-                    pObj->FireSwapOutRequest();
-                    nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0;
-                }
+                pObj->FireSwapOutRequest();
+                nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0;
             }
         }
     }
commit 0ca0202a0994c0b7c99c366fd5cafd8a655df203
Author: Armin Le Grand <alg at apache.org>
Date:   Thu Jun 19 16:49:26 2014 +0000

    Resolves: #i125111# limit mem footprint for GraphicObjects...
    
    in 32Bit environments
    
    Conflicts:
    	svtools/inc/svtools/grfmgr.hxx
    	svtools/source/graphic/grfmgr.cxx
    	svtools/source/graphic/grfmgr2.cxx
    	sw/source/core/doc/notxtfrm.cxx
    	sw/source/core/graphic/ndgrf.cxx
    
    "commit 62b0eaf37c08dd27244e77b8bc90c691b000ebd6
     Related: fdo#50697 reset the cache timeout on GetGraphic
    
     so the graphic gets swapped out Xms after the last use and not Xms after
     initial creation regardless of if it got used a moment earlier."
    
    corrected place for stl sort function for linux
    
    (cherry picked from commit a48414a396f7de4e00510e82e3744c097ce3d5d6)
    
    Conflicts:
    	svtools/source/graphic/grfmgr2.cxx
    
    Change-Id: I79158b7d42629f8dec2bc5565540701bcd3ef6f4
    6f21c7fd4d2681446fc1a6d9607366a1e69165a1

diff --git a/include/svtools/grfmgr.hxx b/include/svtools/grfmgr.hxx
index 251ee6d..4ef7e10 100644
--- a/include/svtools/grfmgr.hxx
+++ b/include/svtools/grfmgr.hxx
@@ -175,6 +175,10 @@ private:
     Timer*                  mpSwapOutTimer;
     GrfSimpleCacheObj*      mpSimpleCache;
     sal_uLong               mnAnimationLoopCount;
+
+    // a unique increasing ID to be able to say which data change is older
+    sal_uLong               mnDataChangeTimeStamp;
+
     bool                    mbAutoSwapped   : 1;
     bool                    mbTransparent   : 1;
     bool                    mbAnimated      : 1;
@@ -299,8 +303,12 @@ private:
 
                             DECL_LINK( ImplAutoSwapOutHdl, void* );
 
-    void SVT_DLLPRIVATE     ResetCacheTimeOut();
+    // restart SwapOut timer; this is like touching in a cache to reset to the full timeout value
+    void SVT_DLLPRIVATE     restartSwapOutTimer() const;
 
+    // Handle evtl. needed AfterDataChanges, needs to be called when new
+    // graphic data is swapped in/added to the GraphicManager
+    void SVT_DLLPRIVATE     ImplAfterDataChange();
 protected:
 
     virtual void            GraphicManagerDestroyed();
@@ -506,6 +514,9 @@ public:
         double fTopCrop,
         double fRightCrop,
         double fBottomCrop) const;
+
+    // read access
+    sal_uLong GetDataChangeTimeStamp() const { return mnDataChangeTimeStamp; }
 };
 
 typedef ::std::vector< GraphicObject* > GraphicObjectList_impl;
@@ -597,12 +608,21 @@ private:
 
     OString SVT_DLLPRIVATE ImplGetUniqueID( const GraphicObject& rObj ) const;
 
+    // This method allows to check memory footprint for all currently swapped in GraphicObjects on this GraphicManager
+    // which are based on Bitmaps. This is needed on 32Bit systems and only does something on those systems. The problem
+    // to solve is that normally the SwapOut is timer-driven, but even with short timer settings there are situations
+    // where this does not trigger - or in other words: A maximum limitation for GraphicManagers was not in place before.
+    // For 32Bit systems this leads to situations where graphics will be missing. This method will actively swap out
+    // the longest swapped in graphics until a maximum memory boundary (derived from user settings in tools/options/memory)
+    // is no longer exceeded
+    void SVT_DLLPRIVATE ImplCheckSizeOfSwappedInGraphics();
 public:
 
                         GraphicManager( sal_uLong nCacheSize = 10000000UL, sal_uLong nMaxObjCacheSize = 2400000UL );
                         ~GraphicManager();
 
     void                SetMaxCacheSize( sal_uLong nNewCacheSize );
+    sal_uLong           GetMaxCacheSize() const;
 
     void                SetMaxObjCacheSize(
                             sal_uLong nNewMaxObjSize,
diff --git a/svtools/source/graphic/grfmgr.cxx b/svtools/source/graphic/grfmgr.cxx
index 408081e..1402ea7 100644
--- a/svtools/source/graphic/grfmgr.cxx
+++ b/svtools/source/graphic/grfmgr.cxx
@@ -59,6 +59,19 @@ struct GrfSimpleCacheObj
 
 TYPEINIT1_AUTOFACTORY( GraphicObject, SvDataCopyStream );
 
+// unique increasing ID for being able to detect the GraphicObject with the
+// oldest last data changes
+static sal_uLong aIncrementingTimeOfLastDataChange = 1;
+
+void GraphicObject::ImplAfterDataChange()
+{
+    // set unique timestamp ID of last data change
+    mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
+
+    // check memory footprint of all GraphicObjects managed and evtl. take action
+    GetGraphicManager().ImplCheckSizeOfSwappedInGraphics();
+}
+
 GraphicObject::GraphicObject( const GraphicManager* pMgr ) :
     maLink      (),
     maUserData  ()
@@ -130,6 +143,9 @@ void GraphicObject::ImplConstruct()
     mbAutoSwapped = false;
     mbIsInSwapIn = false;
     mbIsInSwapOut = false;
+
+    // Init with a unique, increasing ID
+    mnDataChangeTimeStamp = aIncrementingTimeOfLastDataChange++;
 }
 
 void GraphicObject::ImplAssignGraphicData()
@@ -243,6 +259,9 @@ void GraphicObject::ImplAutoSwapIn()
             if( !mbAutoSwapped && mpMgr )
                 mpMgr->ImplGraphicObjectWasSwappedIn( *this );
         }
+
+        // Handle evtl. needed AfterDataChanges
+        ImplAfterDataChange();
     }
 }
 
@@ -744,15 +763,6 @@ void GraphicObject::StopAnimation( OutputDevice* pOut, long nExtraData )
         mpSimpleCache->maGraphic.StopAnimation( pOut, nExtraData );
 }
 
-void GraphicObject::ResetCacheTimeOut()
-{
-    if (mpSwapOutTimer)
-    {
-        mpSwapOutTimer->Stop();
-        mpSwapOutTimer->Start();
-    }
-}
-
 const Graphic& GraphicObject::GetGraphic() const
 {
     GraphicObject *pThis = const_cast<GraphicObject*>(this);
@@ -763,7 +773,7 @@ const Graphic& GraphicObject::GetGraphic() const
     //fdo#50697 If we've been asked to provide the graphic, then reset
     //the cache timeout to start from now and not remain at the
     //time of creation
-    pThis->ResetCacheTimeOut();
+    pThis->restartSwapOutTimer();
 
     return maGraphic;
 }
@@ -785,6 +795,9 @@ void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pC
 
     if( mpSwapOutTimer )
         mpSwapOutTimer->Start();
+
+    // Handle evtl. needed AfterDataChanges
+    ImplAfterDataChange();
 }
 
 void GraphicObject::SetGraphic( const Graphic& rGraphic, const OUString& rLink )
@@ -1101,7 +1114,9 @@ bool GraphicObject::SwapIn()
         bRet = true;
     }
     else if( mpMgr && mpMgr->ImplFillSwappedGraphicObject( *this, maGraphic ) )
+    {
         bRet = true;
+    }
     else
     {
         bRet = maGraphic.SwapIn();
@@ -1111,8 +1126,13 @@ bool GraphicObject::SwapIn()
     }
 
     if( bRet )
+    {
         ImplAssignGraphicData();
 
+        // Handle evtl. needed AfterDataChanges
+        ImplAfterDataChange();
+    }
+
     return bRet;
 }
 
@@ -1297,4 +1317,14 @@ basegfx::B2DVector GraphicObject::calculateCropScaling(
     return basegfx::B2DVector(fFactorX,fFactorY);
 }
 
+// restart SwapOut timer
+void GraphicObject::restartSwapOutTimer() const
+{
+    if( mpSwapOutTimer && mpSwapOutTimer->IsActive() )
+    {
+        mpSwapOutTimer->Stop();
+        mpSwapOutTimer->Start();
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 117a4d0..d5731d8 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -64,6 +64,11 @@ void GraphicManager::SetMaxCacheSize( sal_uLong nNewCacheSize )
     mpCache->SetMaxDisplayCacheSize( nNewCacheSize );
 }
 
+sal_uLong GraphicManager::GetMaxCacheSize() const
+{
+    return mpCache->GetMaxDisplayCacheSize();
+}
+
 void GraphicManager::SetMaxObjCacheSize( sal_uLong nNewMaxObjSize, bool bDestroyGreaterCached )
 {
     mpCache->SetMaxObjDisplayCacheSize( nNewMaxObjSize, bDestroyGreaterCached );
@@ -171,9 +176,81 @@ OString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const
     return mpCache->GetUniqueID( rObj );
 }
 
+namespace
+{
+    struct simpleSortByDataChangeTimeStamp
+    {
+        bool operator() (GraphicObject* p1, GraphicObject* p2) const
+        {
+            return p1->GetDataChangeTimeStamp() < p2->GetDataChangeTimeStamp();
+        }
+    };
+} // end of anonymous namespace
+
+void GraphicManager::ImplCheckSizeOfSwappedInGraphics()
+{
+    // only necessary for 32bit systems
+    if(SAL_TYPES_SIZEOFPOINTER <= 4)
+    {
+        // get the currently used memory footprint of all swapped in bitmap graphics
+        // of this graphic manager. Remember candidates in a vector. The size in bytes is
+        // already available, thus this loop is not expensive to execute
+        sal_uLong nUsedSize(0);
+        GraphicObject* pObj = 0;
+        std::vector< GraphicObject* > aCandidates;
+
+        for (size_t i = 0, n = maObjList.size(); i < n; ++i)
+        {
+            pObj = maObjList[i];
+            if (pObj->meType == GRAPHIC_BITMAP && !pObj->IsSwappedOut() && pObj->GetSizeBytes())
+            {
+                aCandidates.push_back(pObj);
+                nUsedSize += pObj->GetSizeBytes();
+            }
+        }
+
+        // detect maximum allowed memory footprint. Use the user-settings of MaxCacheSize (defaulted
+        // to 20MB) and add a decent multiplicator (expecrimented to find one). Limit to
+        // a useful maximum for 32Bit address space
+
+        // default is 20MB, so allow 200MB initially
+        static sal_uLong aMultiplicator(10);
+
+        // max at 500MB; I experimented with 800 for debug and 750 for non-debug settings (pics start
+        // missing when office reaches a mem footprint of 1.5GB) but some secure left over space for
+        // app activity is needed
+        static sal_uLong aMaxSize32Bit(500 * 1024 * 1024);
+
+        // calc max allowed cache size
+        const sal_uLong nMaxCacheSize(::std::min(GetMaxCacheSize() * aMultiplicator, aMaxSize32Bit));
+
+        if(nUsedSize >= nMaxCacheSize && !aCandidates.empty())
+        {
+            // if we use more currently, sort by last DataChangeTimeStamp
+            // sort by DataChangeTimeStamp so that the oldest get removed first
+            ::std::sort(aCandidates.begin(), aCandidates.end(), simpleSortByDataChangeTimeStamp());
+
+            for(sal_uInt32 a(0); nUsedSize >= nMaxCacheSize && a < aCandidates.size(); a++)
+            {
+                // swap out until we have no more or the goal to use less than nMaxCacheSize
+                // is reached
+                pObj = aCandidates[a];
+                const sal_uLong nSizeBytes(pObj->GetSizeBytes());
+
+                // do not swap out when we have less than 16KB data objects
+                if(nSizeBytes >= (16 * 1024))
+                {
+                    pObj->FireSwapOutRequest();
+                    nUsedSize = (nSizeBytes < nUsedSize) ? nUsedSize - nSizeBytes : 0;
+                }
+            }
+        }
+    }
+}
+
 bool GraphicManager::ImplFillSwappedGraphicObject( const GraphicObject& rObj, Graphic& rSubstitute )
 {
-    return( mpCache->FillSwappedGraphicObject( rObj, rSubstitute ) );
+    return mpCache->FillSwappedGraphicObject(rObj, rSubstitute);
 }
 
 void GraphicManager::ImplGraphicObjectWasSwappedIn( const GraphicObject& rObj )
diff --git a/vcl/win/source/gdi/salbmp.cxx b/vcl/win/source/gdi/salbmp.cxx
index 445839e..2bccbd7 100644
--- a/vcl/win/source/gdi/salbmp.cxx
+++ b/vcl/win/source/gdi/salbmp.cxx
@@ -453,35 +453,43 @@ Gdiplus::Bitmap* WinSalBitmap::ImplCreateGdiPlusBitmap(const WinSalBitmap& rAlph
 
         if(pRetval)
         {
-            sal_uInt8* pSrcRGB(pRGB->mpBits);
-            sal_uInt8* pSrcA(pA->mpBits);
-            const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
-            const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
-            const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
-            const Gdiplus::Rect aAllRect(0, 0, nW, nH);
-            Gdiplus::BitmapData aGdiPlusBitmapData;
-            pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData);
-
-            // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and
-            // A from alpha, so inner loop is needed (who invented BitmapEx..?)
-            for(sal_uInt32 y(0); y < nH; y++)
+            if ( pRetval->GetLastStatus() == Gdiplus::Ok ) // 2nd place to secure with new Gdiplus::Bitmap
             {
-                const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
-                sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride);
+                sal_uInt8* pSrcRGB(pRGB->mpBits);
+                sal_uInt8* pSrcA(pA->mpBits);
+                const sal_uInt32 nExtraRGB(pRGB->mnScanlineSize - (nW * 3));
+                const sal_uInt32 nExtraA(pA->mnScanlineSize - nW);
+                const bool bTopDown(pRGB->mnFormat & BMP_FORMAT_TOP_DOWN);
+                const Gdiplus::Rect aAllRect(0, 0, nW, nH);
+                Gdiplus::BitmapData aGdiPlusBitmapData;
+                pRetval->LockBits(&aAllRect, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &aGdiPlusBitmapData);
 
-                for(sal_uInt32 x(0); x < nW; x++)
+                // copy data to Gdiplus::Bitmap; format is BGRA; need to mix BGR from Bitmap and
+                // A from alpha, so inner loop is needed (who invented BitmapEx..?)
+                for(sal_uInt32 y(0); y < nH; y++)
                 {
-                    *targetPixels++ = *pSrcRGB++;
-                    *targetPixels++ = *pSrcRGB++;
-                    *targetPixels++ = *pSrcRGB++;
-                    *targetPixels++ = 0xff - *pSrcA++;
+                    const sal_uInt32 nYInsert(bTopDown ? y : nH - y - 1);
+                    sal_uInt8* targetPixels = (sal_uInt8*)aGdiPlusBitmapData.Scan0 + (nYInsert * aGdiPlusBitmapData.Stride);
+
+                    for(sal_uInt32 x(0); x < nW; x++)
+                    {
+                        *targetPixels++ = *pSrcRGB++;
+                        *targetPixels++ = *pSrcRGB++;
+                        *targetPixels++ = *pSrcRGB++;
+                        *targetPixels++ = 0xff - *pSrcA++;
+                    }
+
+                    pSrcRGB += nExtraRGB;
+                    pSrcA += nExtraA;
                 }
 
-                pSrcRGB += nExtraRGB;
-                pSrcA += nExtraA;
+                pRetval->UnlockBits(&aGdiPlusBitmapData);
+            }
+            else
+            {
+                delete pRetval;
+                pRetval = NULL;
             }
-
-            pRetval->UnlockBits(&aGdiPlusBitmapData);
         }
     }
 


More information about the Libreoffice-commits mailing list