drawinglayer/source/processor2d/cairopixelprocessor2d.cxx |   16 +++++++++++
 include/vcl/bitmap.hxx                                    |    5 +++
 vcl/source/bitmap/bitmap.cxx                              |   20 ++++++++++++++
 3 files changed, 41 insertions(+)

New commits:
commit d2accdad4b6d7c301c24b24c7b964183340746d4
Author:     Armin Le Grand (allotropia) <[email protected]>
AuthorDate: Thu Apr 17 00:37:27 2025 +0200
Commit:     Noel Grandin <[email protected]>
CommitDate: Sat Oct 25 09:30:35 2025 +0200

    reduce memory usage when rendering cairo-backed Bitmaps
    
    Change-Id: I1353e8fb044203b377c2a1f17767f690a9796367
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184301
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <[email protected]>

diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
index fce75417ac0c..9fb4991ebb36 100644
--- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
@@ -62,6 +62,7 @@
 #include <unordered_map>
 #include <dlfcn.h>
 #include "vclhelperbufferdevice.hxx"
+#include <iostream>
 
 using namespace com::sun::star;
 
@@ -552,6 +553,13 @@ public:
 #endif
     }
 
+    /* constructor for when we are using the cairo data directly from the 
underlying SvpSalBitmap */
+    CairoSurfaceHelper(cairo_surface_t* pCairoSurface)
+        : mpCairoSurface(pCairoSurface)
+        , maDownscaled()
+    {
+    }
+
     ~CairoSurfaceHelper()
     {
         // cleanup surface
@@ -704,6 +712,14 @@ sal_Int64 
SystemDependentData_CairoSurface::estimateUsageInBytes() const
 
 std::shared_ptr<CairoSurfaceHelper> getOrCreateCairoSurfaceHelper(const 
Bitmap& rBitmap)
 {
+    // When using a cairo-backed Bitmap (i.e. SvpSalBitmap), we can avoid a 
lot of copying,
+    // which is beneficial for documents with lots of large images.
+    cairo_surface_t* 
pSurface(static_cast<cairo_surface_t*>(rBitmap.tryToGetCairoSurface()));
+    if (nullptr != pSurface)
+    {
+        return std::make_shared<CairoSurfaceHelper>(pSurface);
+    }
+
     const basegfx::SystemDependentDataHolder* 
pHolder(rBitmap.accessSystemDependentDataHolder());
     std::shared_ptr<SystemDependentData_CairoSurface> 
pSystemDependentData_CairoSurface;
 
diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx
index b8704fe60095..e2f2f5853ffa 100644
--- a/include/vcl/bitmap.hxx
+++ b/include/vcl/bitmap.hxx
@@ -30,6 +30,7 @@
 #include <vcl/mapmod.hxx>
 #include <vcl/region.hxx>
 #include <vcl/bitmap/BitmapTypes.hxx>
+#include <config_vclplug.h>
 
 #include <o3tl/typed_flags_set.hxx>
 #include <com/sun/star/uno/Sequence.hxx>
@@ -718,6 +719,10 @@ public:
     /// Dumps the pixels as PNG in bitmap.png.
     void DumpAsPng(const char* pFileName = nullptr) const;
 
+#if USE_HEADLESS_CODE
+    void* tryToGetCairoSurface() const;
+#endif
+
 private:
     SAL_DLLPRIVATE bool ImplConvertUp(vcl::PixelFormat ePixelFormat, Color 
const* pExtColor = nullptr);
     SAL_DLLPRIVATE bool ImplConvertDown8BPP(Color const* pExtColor = nullptr);
diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx
index f0404fa80a18..a157215f8597 100644
--- a/vcl/source/bitmap/bitmap.cxx
+++ b/vcl/source/bitmap/bitmap.cxx
@@ -64,6 +64,11 @@
 #include <vcl/graphicfilter.hxx>
 #endif
 
+#if USE_HEADLESS_CODE
+#include <headless/svpbmp.hxx>
+#include <headless/CairoCommon.hxx>
+#endif
+
 Bitmap::Bitmap()
 {
 }
@@ -380,6 +385,21 @@ Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
     return *this;
 }
 
+#if USE_HEADLESS_CODE
+void* Bitmap::tryToGetCairoSurface() const
+{
+    SvpSalBitmap* 
pSvpSalBitmap(dynamic_cast<SvpSalBitmap*>(ImplGetSalBitmap().get()));
+    if (nullptr == pSvpSalBitmap)
+        return nullptr;
+
+    const BitmapBuffer* pBitmapBuffer(pSvpSalBitmap->GetBuffer());
+    if (nullptr == pBitmapBuffer)
+        return nullptr;
+
+    return CairoCommon::createCairoSurface(pBitmapBuffer);
+}
+#endif
+
 Bitmap& Bitmap::operator=( Bitmap&& rBitmap ) noexcept
 {
     maPrefSize = std::move(rBitmap.maPrefSize);

Reply via email to