[Libreoffice-commits] core.git: Branch 'private/Ashod/cd-5.3-3.2_import_unloaded' - 10 commits - basctl/inc basic/source canvas/source chart2/CppunitTest_chart2_export.mk chart2/CppunitTest_chart2_import.mk chart2/CppunitTest_chart2_trendcalculators.mk chart2/CppunitTest_chart2_xshape.mk chart2/inc chart2/source compilerplugins/clang cppcanvas/CppunitTest_cppcanvas_emfplus.mk cui/inc cui/source dbaccess/source desktop/CppunitTest_desktop_lib.mk drawinglayer/source editeng/source filter/source include/drawinglayer include/editeng include/filter include/oox include/svtools include/svx include/vcl offapi/com offapi/UnoApi_offapi.mk oox/source postprocess/Rdb_services.mk reportdesign/inc sc/CppunitTest_sc_anchor_test.mk sc/CppunitTest_sc_annotationobj.mk sc/CppunitTest_sc_annotationshapeobj.mk sc/CppunitTest_sc_annotationsobj.mk sc/CppunitTest_sc_bugfix_test.mk sc/CppunitTest_sc_cellrangeobj.mk sc/CppunitTest_sc_chart_regression_test.mk sc/CppunitTest_sc_check_data_pilot_field.mk sc/CppunitTest_sc_ch eck_data_pilot_table.mk sc/CppunitTest_sc_check_xcell_ranges_query.mk sc/CppunitTest_sc_condformats.mk sc/CppunitTest_sc_copypaste.mk sc/CppunitTest_sc_databaserangeobj.mk sc/CppunitTest_sc_datapilotfieldobj.mk sc/CppunitTest_sc_datapilottableobj.mk sc/CppunitTest_sc_editfieldobj_cell.mk sc/CppunitTest_sc_editfieldobj_header.mk sc/CppunitTest_sc_filters_test.mk sc/CppunitTest_sc_html_export_test.mk sc/CppunitTest_sc_macros_test.mk sc/CppunitTest_sc_mark_test.mk sc/CppunitTest_sc_modelobj.mk sc/CppunitTest_sc_namedrangeobj.mk sc/CppunitTest_sc_namedrangesobj.mk sc/CppunitTest_sc_new_cond_format_api.mk sc/CppunitTest_sc_opencl_test.mk sc/CppunitTest_sc_outlineobj.mk sc/CppunitTest_sc_rangelst_test.mk sc/CppunitTest_sc_recordchanges.mk sc/CppunitTest_sc_styleloaderobj.mk sc/CppunitTest_sc_subsequent_export_test.mk sc/CppunitTest_sc_subsequent_filters_test.mk sc/CppunitTest_sc_tablesheetobj.mk sc/CppunitTest_sc_tablesheetsobj.mk sc/CppunitTest_sc_ucalc.mk sc/CppunitTest_sc_viewpaneobj.m k sc/inc sc/Module_sc.mk sc/qa sd/CppunitTest_sd_filters_test.mk sd/CppunitTest_sd_html_export_tests.mk sd/CppunitTest_sd_import_tests.mk sd/CppunitTest_sd_misc_tests.mk sd/inc sd/qa sd/source slideshow/source solenv/bin svtools/inc svtools/Library_svt.mk svtools/qa svtools/source svtools/util svx/inc svx/source sw/CppunitTest_sw_filters_test.mk sw/CppunitTest_sw_htmlexport.mk sw/CppunitTest_sw_macros_test.mk sw/CppunitTest_sw_mailmerge.mk sw/CppunitTest_sw_odfimport.mk sw/CppunitTest_sw_ooxmlexport8.mk sw/CppunitTest_sw_ooxmlimport.mk sw/CppunitTest_sw_rtfimport.mk sw/CppunitTest_sw_ww8export2.mk sw/CppunitTest_sw_ww8export.mk sw/CppunitTest_sw_ww8import.mk sw/inc sw/ooxmlexport_setup.mk sw/qa sw/source vcl/inc vcl/Library_vcl.mk vcl/source vcl/vcl.common.component vcl/workben writerfilter/CppunitTest_writerfilter_rtftok.mk writerfilter/source

Ashod Nakashian ashod.nakashian at collabora.co.uk
Mon Jun 18 13:16:19 UTC 2018


Rebased ref, commits from common ancestor:
commit 3758520725a2a648bd8710b7f2ec30ebcfabbf9a
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sat Jun 9 15:31:42 2018 -0400

    vcl: maintain shared PdfData across swap-in and -out
    
    Change-Id: I6e434e5b5db0ddcd2fb4d1e522ffdb1c963c1f34

diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index 2656a2b7dd7f..ad7609be7091 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -268,12 +268,21 @@ bool ImportPDF(SvStream& rStream, Graphic& rGraphic,
     if (rGraphic.getPageNumber() < 0)
         rGraphic.setPageNumber(0);
 
-    uno::Sequence<sal_Int8> aPdfData;
+    if (rGraphic.getPdfData() == nullptr)
+        rGraphic.setPdfData(std::make_shared<css::uno::Sequence<sal_Int8>>());
+
+    // Preserve the PdfData, if exists, as it's shared.
+    std::shared_ptr<css::uno::Sequence<sal_Int8>> pPdfData = rGraphic.getPdfData();
+
     Bitmap aBitmap;
-    const bool bRet = ImportPDF(rStream, aBitmap, rGraphic.getPageNumber(), aPdfData,
+    const bool bRet = ImportPDF(rStream, aBitmap, rGraphic.getPageNumber(), *pPdfData,
                                 STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END, fResolutionDPI);
+
+    // Assign the bitmap; will clobber PdfData.
     rGraphic = aBitmap;
-    rGraphic.setPdfData(std::make_shared<css::uno::Sequence<sal_Int8>>(aPdfData));
+
+    // Set PdfData.
+    rGraphic.setPdfData(pPdfData);
     return bRet;
 }
 
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 7eed3bfc34a6..004c315a8ea7 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -392,11 +392,13 @@ bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
 
 void ImpGraphic::setPdfData(const std::shared_ptr<uno::Sequence<sal_Int8>>& rPdfData)
 {
+    // No need to swap-in graphic when setting optional PDF data.
     mpPdfData = rPdfData;
 }
 
 const std::shared_ptr<uno::Sequence<sal_Int8>>& ImpGraphic::getPdfData() const
 {
+    // No need to swap-in graphic when getting optional PDF data.
     return mpPdfData;
 }
 
@@ -1423,8 +1425,12 @@ bool ImpGraphic::ensureAvailable() const
 bool ImpGraphic::loadPrepared()
 {
     Graphic aGraphic;
+
     // Set the page number to load the correct page (for multipage types).
     aGraphic.setPageNumber(mnPageNumber);
+    // Preserve the PdfData since it's shared.
+    aGraphic.setPdfData(getPdfData());
+
     if (mpGfxLink->LoadNative(aGraphic))
     {
         *this = *aGraphic.ImplGetImpGraphic();
commit 47dc8c516ec0498ef19286b7b6bb6da9ae1671c4
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sat Jun 9 13:09:35 2018 -0400

    vcl: sd: import PDF as unloaded images
    
    Change-Id: Ibf9afeab2cb580a245af666b906310de1c9b351f

diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx
index 5d79c6d38146..5e482850d58d 100644
--- a/include/vcl/pdfread.hxx
+++ b/include/vcl/pdfread.hxx
@@ -10,16 +10,33 @@
 #ifndef INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX
 #define INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX
 
+#include <vector>
 #include <tools/stream.hxx>
 #include <vcl/graph.hxx>
+#include <tools/gen.hxx>
+
+namespace com
+{
+namespace sun
+{
+namespace star
+{
+namespace uno
+{
+template <typename> class Sequence;
+}
+}
+}
+}
+class Bitmap;
+class Graphic;
 
 namespace vcl
 {
 
 /// Imports a PDF stream into rGraphic as a GDIMetaFile.
-VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap &rBitmap,
-                             size_t nPageIndex,
-                             css::uno::Sequence<sal_Int8> &rPdfFata,
+VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex,
+                             css::uno::Sequence<sal_Int8>& rPdfData,
                              sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN,
                              sal_uInt64 nSize = STREAM_SEEK_TO_END,
                              const double fResolutionDPI = 96.);
@@ -27,10 +44,17 @@ VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap &rBitmap,
 VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic,
                              const double fResolutionDPI = 96.);
 
-VCL_DLLPUBLIC size_t ImportPDF(const OUString& rURL,
-                               std::vector<Bitmap>& rBitmaps,
+VCL_DLLPUBLIC size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps,
                                css::uno::Sequence<sal_Int8>& rPdfData,
                                const double fResolutionDPI = 96.);
+
+/// Import PDF as Graphic images (1 per page), all unloaded.
+/// Since Graphic is unloaded, we need to return the page size (in pixels) separately.
+/// Does not set rPdfData if no conversion is done.
+/// Returns the number of pages read.
+VCL_DLLPUBLIC size_t ImportPDFUnloaded(const OUString& rURL,
+                                       std::vector<std::pair<Graphic, Size>>& rGraphics,
+                                       const double fResolutionDPI = 96.);
 }
 
 #endif // INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX
diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx
index 538c4e1ec44a..62dbc3964f35 100644
--- a/sd/source/filter/pdf/sdpdffilter.cxx
+++ b/sd/source/filter/pdf/sdpdffilter.cxx
@@ -102,37 +102,29 @@ bool SdPdfFilter::Import()
     // Rendering resolution.
     const double dResolutionDPI = 96.;
 
-    uno::Sequence<sal_Int8> aPdfData;
-    std::vector<Bitmap> aBitmaps;
-    if (vcl::ImportPDF(aFileName, aBitmaps, aPdfData, dResolutionDPI) == 0)
+    std::vector<std::pair<Graphic, Size>> aGraphics;
+    if (vcl::ImportPDFUnloaded(aFileName, aGraphics, dResolutionDPI) == 0)
         return false;
 
-    // Prepare the link with the PDF stream.
-    const size_t nGraphicContentSize = aPdfData.getLength();
-    std::unique_ptr<sal_uInt8[]> pGraphicContent(new sal_uInt8[nGraphicContentSize]);
-    memcpy(pGraphicContent.get(), aPdfData.get(), nGraphicContentSize);
-    GfxLink aGfxLink(std::move(pGraphicContent), nGraphicContentSize, GfxLinkType::NativePdf);
-    auto pPdfData = std::make_shared<uno::Sequence<sal_Int8>>(aPdfData);
-
+    // Add as many pages as we need up-front.
     mrDocument.CreateFirstPages();
-    for (size_t i = 0; i < aBitmaps.size() - 1; ++i)
+    for (int i = 0; i < aGraphics.size() - 1; ++i)
     {
         mrDocument.DuplicatePage(0);
     }
 
-    size_t nPageNumber = 0;
-    for (Bitmap& aBitmap : aBitmaps)
+    for (std::pair<Graphic, Size>& aPair : aGraphics)
     {
-        // Create the Graphic and link the original PDF stream.
-        Graphic aGraphic(aBitmap);
-        aGraphic.setPdfData(pPdfData);
-        aGraphic.setPageNumber(nPageNumber);
-        aGraphic.SetGfxLink(aGfxLink);
-        aGraphic.setOriginURL(aFileName);
+        const Graphic& aGraphic = aPair.first;
+        const Size& aSize = aPair.second;
+
+        const sal_Int32 nPageNumber = aGraphic.getPageNumber();
+        if (nPageNumber < 0 || nPageNumber >= aGraphics.size())
+            continue; // Page is out of range
 
         // Create the page and insert the Graphic.
-        SdPage* pPage = mrDocument.GetSdPage(nPageNumber++, PageKind::Standard);
-        Size aGrfSize(OutputDevice::LogicToLogic(aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(),
+        SdPage* pPage = mrDocument.GetSdPage(nPageNumber, PageKind::Standard);
+        Size aGrfSize(OutputDevice::LogicToLogic(aSize, aGraphic.GetPrefMapMode(),
                                                  MapMode(MapUnit::Map100thMM)));
 
         // Resize to original size based on 72 dpi to preserve page size.
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index 016616e69dfc..2656a2b7dd7f 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -23,8 +23,10 @@
 #endif
 #endif
 
-#include <vcl/bitmapaccess.hxx>
+#include <impgraph.hxx>
+
 #include <vcl/graph.hxx>
+#include <vcl/bitmapaccess.hxx>
 #include <unotools/ucbstreamhelper.hxx>
 
 using namespace com::sun::star;
@@ -297,6 +299,75 @@ size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps,
 
     return rBitmaps.size();
 }
+
+size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Size>>& rGraphics,
+                         const double fResolutionDPI)
+{
+    std::unique_ptr<SvStream> xStream(
+        ::utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ | StreamMode::SHARE_DENYNONE));
+
+    // Save the original PDF stream for later use.
+    SvMemoryStream aMemoryStream;
+    if (!getCompatibleStream(*xStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END))
+        return 0;
+
+    // Copy into PdfData
+    uno::Sequence<sal_Int8> aPdfData;
+    aMemoryStream.Seek(STREAM_SEEK_TO_END);
+    aPdfData = css::uno::Sequence<sal_Int8>(aMemoryStream.Tell());
+    aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
+    aMemoryStream.ReadBytes(aPdfData.getArray(), aPdfData.getLength());
+
+    // Prepare the link with the PDF stream.
+    const size_t nGraphicContentSize = aPdfData.getLength();
+    std::unique_ptr<sal_uInt8[]> pGraphicContent(new sal_uInt8[nGraphicContentSize]);
+    memcpy(pGraphicContent.get(), aPdfData.get(), nGraphicContentSize);
+    GfxLink aGfxLink(GfxLink(std::move(pGraphicContent), nGraphicContentSize, GfxLinkType::NativePdf));
+    auto pPdfData = std::make_shared<uno::Sequence<sal_Int8>>(aPdfData);
+
+    FPDF_LIBRARY_CONFIG aConfig;
+    aConfig.version = 2;
+    aConfig.m_pUserFontPaths = nullptr;
+    aConfig.m_pIsolate = nullptr;
+    aConfig.m_v8EmbedderSlot = 0;
+    FPDF_InitLibraryWithConfig(&aConfig);
+
+    // Load the buffer using pdfium.
+    FPDF_DOCUMENT pPdfDocument
+        = FPDF_LoadMemDocument(aPdfData.getArray(), aPdfData.getLength(), /*password=*/nullptr);
+    if (!pPdfDocument)
+        return 0;
+
+    const int nPageCount = FPDF_GetPageCount(pPdfDocument);
+    if (nPageCount <= 0)
+        return 0;
+
+    for (size_t nPageIndex = 0; nPageIndex < static_cast<size_t>(nPageCount); ++nPageIndex)
+    {
+        double fPageWidth = 0;
+        double fPageHeight = 0;
+        if (FPDF_GetPageSizeByIndex(pPdfDocument, nPageIndex, &fPageWidth, &fPageHeight) == 0)
+            continue;
+
+        // Returned unit is points, convert that to pixel.
+        const size_t nPageWidth = pointToPixel(fPageWidth, fResolutionDPI);
+        const size_t nPageHeight = pointToPixel(fPageHeight, fResolutionDPI);
+
+        // Create the Graphic and link the original PDF stream.
+        Graphic aGraphic;
+        aGraphic.setPdfData(pPdfData); // TODO: Skip if unchanged.
+        aGraphic.setPageNumber(nPageIndex);
+        aGraphic.SetGfxLink(aGfxLink);
+        aGraphic.ImplGetImpGraphic()->ImplSetPrepared(); // Prepared but not loaded.
+
+        rGraphics.emplace_back(std::move(aGraphic), Size(nPageWidth, nPageHeight));
+    }
+
+    FPDF_CloseDocument(pPdfDocument);
+    FPDF_DestroyLibrary();
+
+    return rGraphics.size();
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 4f7e4601777dbdc20584ac93b651a7a4c4537942
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Sat Jun 9 13:01:24 2018 -0400

    vcl: load the correct page when swapping-in a PDF Graphic
    
    Change-Id: I00ffb9f76e763e1c4cd65c5dcea061d6d94d1d6a

diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 78f92dd7b79b..68dbbedfb207 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -2080,6 +2080,7 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPat
         }
         else if (aFilterName == IMP_PDF)
         {
+            // Note: will import rGraphic.getPageNumber if non-negative, or the first.
             if (!vcl::ImportPDF(rIStream, rGraphic))
                 nStatus = GRFILTER_FILTERERROR;
             else
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index af8f3ab38c06..016616e69dfc 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -262,14 +262,16 @@ bool ImportPDF(SvStream& rStream, Bitmap &rBitmap,
 bool ImportPDF(SvStream& rStream, Graphic& rGraphic,
                const double fResolutionDPI)
 {
+    // Load the first page implicitly, if a specific one is not requested.
+    if (rGraphic.getPageNumber() < 0)
+        rGraphic.setPageNumber(0);
+
     uno::Sequence<sal_Int8> aPdfData;
     Bitmap aBitmap;
-    bool bRet = ImportPDF(rStream, aBitmap, 0, aPdfData,
-                          STREAM_SEEK_TO_BEGIN,
-                          STREAM_SEEK_TO_END, fResolutionDPI);
+    const bool bRet = ImportPDF(rStream, aBitmap, rGraphic.getPageNumber(), aPdfData,
+                                STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END, fResolutionDPI);
     rGraphic = aBitmap;
     rGraphic.setPdfData(std::make_shared<css::uno::Sequence<sal_Int8>>(aPdfData));
-    rGraphic.setPageNumber(0); // We currently import only the first page.
     return bRet;
 }
 
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 798022e8f9f4..7eed3bfc34a6 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -1423,6 +1423,8 @@ bool ImpGraphic::ensureAvailable() const
 bool ImpGraphic::loadPrepared()
 {
     Graphic aGraphic;
+    // Set the page number to load the correct page (for multipage types).
+    aGraphic.setPageNumber(mnPageNumber);
     if (mpGfxLink->LoadNative(aGraphic))
     {
         *this = *aGraphic.ImplGetImpGraphic();
commit 1bd83ce128504f137de0aeb3c979b85ac5c2b810
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Sat Apr 14 15:13:05 2018 +0900

    Function to load graphic swapped out (loaded on demand)
    
    When a document is loaded it takes a lot of time and memory to
    load the graphic that are in the documet, so avoid that and just
    store the compressed graphic into a temporary file (handeled by
    GfxLink) and load when we really need to show the graphic.
    
    GraphicObject cached some attributes from Graphic, but this
    attributes now aren't available immediately so this attributes
    are removed form GraphicObject and now delegate to the Graphic
    itself. GetSizeBytes attribute however was removed as it is
    only used in some tests.
    
    GfxLink initial values were moved to the constructor and are
    not set in the header file anymore (as it is the recommended
    way to do it).
    
    The SdImportTest::testDocumentLayout failed as it looks like the
    dump sometimes didn't include the width and height of the null
    bitmap (which is set to 32x32) of the FillBitmap in some
    situations, but then in other situations it did include this
    attributes. With this change the width and height are always
    included for the FillBitmap which looks like it is more correct.
    
    Reviewed-on: https://gerrit.libreoffice.org/53016
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 7b355669c6ddeab2e6cec692d6afdff41c61d0fb)
    
    Change-Id: Ia1218f93b1735402b7828404f65660e2d4acf32f

diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx
index 9e39ebb64e64..c0f5ad7a334e 100644
--- a/include/svx/svdograf.hxx
+++ b/include/svx/svdograf.hxx
@@ -144,8 +144,8 @@ public:
     bool IsEPS() const;
     bool IsSwappedOut() const;
 
-    const MapMode&          GetGrafPrefMapMode() const;
-    const Size&             GetGrafPrefSize() const;
+    MapMode          GetGrafPrefMapMode() const;
+    Size             GetGrafPrefSize() const;
 
     void                    SetGrafStreamURL( const OUString& rGraphicStreamURL );
     OUString                GetGrafStreamURL() const;
diff --git a/include/vcl/GraphicObject.hxx b/include/vcl/GraphicObject.hxx
index 888109343e37..1ad14e01216f 100644
--- a/include/vcl/GraphicObject.hxx
+++ b/include/vcl/GraphicObject.hxx
@@ -202,6 +202,7 @@ private:
     void                    VCL_DLLPRIVATE ImplAssignGraphicData();
     static void             VCL_DLLPRIVATE ImplEnsureGraphicManager();
     void                    VCL_DLLPRIVATE ImplAutoSwapIn();
+
     bool                    VCL_DLLPRIVATE ImplGetCropParams(
                                 OutputDevice* pOut,
                                 Point& rPt,
@@ -396,14 +397,6 @@ public:
 
     OString                 GetUniqueID() const;
 
-    GraphicType             GetType() const { return meType; }
-    const Size&             GetPrefSize() const { return maPrefSize; }
-    const MapMode&          GetPrefMapMode() const { return maPrefMapMode; }
-    sal_uLong               GetSizeBytes() const { return mnSizeBytes; }
-    bool                    IsTransparent() const { return mbTransparent; }
-    bool                    IsAnimated() const { return mbAnimated; }
-    bool                    IsEPS() const { return mbEPS; }
-
     bool                    SwapOut();
     bool                    SwapOut( SvStream* pOStm );
     bool                    SwapIn();
@@ -412,6 +405,13 @@ public:
     bool                    IsInSwapOut() const { return mbIsInSwapOut; }
     bool                    IsSwappedOut() const { return( mbAutoSwapped || maGraphic.IsSwapOut() ); }
 
+    GraphicType             GetType() const;
+    Size                    GetPrefSize() const;
+    MapMode                 GetPrefMapMode() const;
+    bool                    IsTransparent() const;
+    bool                    IsAnimated() const;
+    bool                    IsEPS() const;
+
     bool                    Draw(
                                 OutputDevice* pOut,
                                 const Point& rPt,
diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx
index d8eef9e3ce3a..bb0fc0af7493 100644
--- a/include/vcl/gfxlink.hxx
+++ b/include/vcl/gfxlink.hxx
@@ -64,17 +64,17 @@ private:
 
     };
 
-    GfxLinkType     meType = GfxLinkType::NONE;
-    sal_uInt32      mnUserId = 0;
+    GfxLinkType     meType;
+    sal_uInt32      mnUserId;
 
     std::shared_ptr<sal_uInt8> mpSwapInData;
     std::shared_ptr<SwapOutData> mpSwapOutData;
 
-    sal_uInt32      mnSwapInDataSize = 0;
+    sal_uInt32      mnSwapInDataSize;
     MapMode         maPrefMapMode;
     Size            maPrefSize;
-    bool            mbPrefMapModeValid = false;
-    bool            mbPrefSizeValid = false;
+    bool            mbPrefMapModeValid;
+    bool            mbPrefSizeValid;
 
     SAL_DLLPRIVATE std::shared_ptr<sal_uInt8> GetSwapInData() const;
 public:
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index 1676b883c4d6..5e6a47b09559 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -141,6 +141,9 @@ public:
     bool            IsAnimated() const;
     bool            IsEPS() const;
 
+    bool isAvailable() const;
+    bool makeAvailable();
+
     // #i102089# Access of Bitmap potentially will have to rasterconvert the Graphic
     // if it is a MetaFile. To be able to control this conversion it is necessary to
     // allow giving parameters which control AntiAliasing and LineSnapping of the
diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index 8b8a7cef3008..f9e727a50051 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -100,6 +100,7 @@ namespace o3tl
 #define WMF_SHORTNAME           "WMF"
 #define EMF_SHORTNAME           "EMF"
 #define SVG_SHORTNAME           "SVG"
+#define PDF_SHORTNAME           "PDF"
 
 //  Info class for all supported file formats
 
@@ -283,6 +284,11 @@ public:
                                    sal_uInt16 * pDeterminedFormat = nullptr, GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE,
                                    WMF_EXTERNALHEADER *pExtHeader = nullptr );
 
+    /// Imports multiple graphics.
+    ///
+    /// The resulting graphic is added to rGraphics on success, nullptr is added on failure.
+    void ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, const std::vector< std::shared_ptr<SvStream> >& rStreams);
+
     sal_uInt16          ImportGraphic( Graphic& rGraphic, const OUString& rPath,
                                    SvStream& rStream,
                                    sal_uInt16 nFormat,
@@ -290,6 +296,8 @@ public:
                                    css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
                                    WMF_EXTERNALHEADER *pExtHeader = nullptr );
 
+    Graphic ImportUnloadedGraphic(SvStream& rIStream);
+
     const FilterErrorEx&    GetLastError() const { return *pErrorEx;}
     void                    ResetLastError();
 
diff --git a/include/vcl/salctype.hxx b/include/vcl/salctype.hxx
index 409fc5a79993..893adb4d47e4 100644
--- a/include/vcl/salctype.hxx
+++ b/include/vcl/salctype.hxx
@@ -37,7 +37,8 @@ enum class ConvertDataFormat
     TIF,
     WMF,
     EMF,
-    SVG
+    SVG,
+    PDF
 };
 
 class SvStream;
diff --git a/sc/qa/extras/anchor.cxx b/sc/qa/extras/anchor.cxx
index 823370529e0c..cb66feafaa0f 100644
--- a/sc/qa/extras/anchor.cxx
+++ b/sc/qa/extras/anchor.cxx
@@ -77,7 +77,7 @@ void ScAnchorTest::testUndoAnchor()
     const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true);
     CPPUNIT_ASSERT(!rGraphicObj.IsSwappedOut());
     CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes());
+    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
     // Get the document controller
     ScTabViewShell* pViewShell = pDocSh->GetBestViewShell(false);
@@ -111,14 +111,14 @@ void ScAnchorTest::testUndoAnchor()
     // Check anchor type
     CPPUNIT_ASSERT(oldType == ScDrawLayer::GetAnchorType(*pObject) );
     CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes());
+    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
     pUndoMgr->Redo();
 
     // Check anchor type
     CPPUNIT_ASSERT(newType == ScDrawLayer::GetAnchorType(*pObject) );
     CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes());
+    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
     ScDrawLayer::SetPageAnchored(*pObject);
     // Check state
@@ -136,14 +136,14 @@ void ScAnchorTest::testUndoAnchor()
     // Check anchor type
     CPPUNIT_ASSERT(oldType == ScDrawLayer::GetAnchorType(*pObject) );
     CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes());
+    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
     pUndoMgr->Redo();
 
     // Check anchor type
     CPPUNIT_ASSERT(newType == ScDrawLayer::GetAnchorType(*pObject) );
     CPPUNIT_ASSERT_EQUAL(int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetSizeBytes());
+    CPPUNIT_ASSERT_EQUAL(sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
     xComponent->dispose();
 }
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 793b239d510d..3dd6528be557 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -3532,7 +3532,7 @@ void ScExportTest::testLinkedGraphicRT()
         const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true);
         CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), !rGraphicObj.IsSwappedOut());
         CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-        CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes());
+        CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
         xDocSh2->DoClose();
     }
diff --git a/sd/qa/unit/data/xml/fdo64586_0.xml b/sd/qa/unit/data/xml/fdo64586_0.xml
index a2487832299c..4ba0afe041a5 100644
--- a/sd/qa/unit/data/xml/fdo64586_0.xml
+++ b/sd/qa/unit/data/xml/fdo64586_0.xml
@@ -4,7 +4,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
@@ -18,7 +18,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
diff --git a/sd/qa/unit/data/xml/n758621_0.xml b/sd/qa/unit/data/xml/n758621_0.xml
index 754be1d41ed1..dc3e0935cc3e 100644
--- a/sd/qa/unit/data/xml/n758621_0.xml
+++ b/sd/qa/unit/data/xml/n758621_0.xml
@@ -4,7 +4,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
@@ -18,7 +18,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
diff --git a/sd/qa/unit/data/xml/n758621_1.xml b/sd/qa/unit/data/xml/n758621_1.xml
index 0f71931585bb..0b826248fdc9 100644
--- a/sd/qa/unit/data/xml/n758621_1.xml
+++ b/sd/qa/unit/data/xml/n758621_1.xml
@@ -4,7 +4,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
@@ -18,7 +18,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
diff --git a/sd/qa/unit/data/xml/n819614_0.xml b/sd/qa/unit/data/xml/n819614_0.xml
index aff9c324344c..ee1925a3bbc2 100644
--- a/sd/qa/unit/data/xml/n819614_0.xml
+++ b/sd/qa/unit/data/xml/n819614_0.xml
@@ -4,7 +4,7 @@
   <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="000000" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
-  <FillBitmap/>
+  <FillBitmap width="32" height="32"/>
   <LineDash style="RECT" dots="1" dotLen="20" dashes="1" dashLen="20" distance="20"/>
   <LineStart/>
   <LineEnd/>
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index a1f067287de5..0bba77ba2c24 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -512,9 +512,8 @@ void SdExportTest::testLinkedGraphicRT()
         CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pObject->IsLinkedGraphic() );
 
         const GraphicObject& rGraphicObj = pObject->GetGraphicObject(true);
-        CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), !rGraphicObj.IsSwappedOut());
         CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetGraphic().GetType()));
-        CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetSizeBytes());
+        CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), sal_uLong(864900), rGraphicObj.GetGraphic().GetSizeBytes());
 
         xDocShRef->DoClose();
     }
diff --git a/svtools/qa/unit/GraphicObjectTest.cxx b/svtools/qa/unit/GraphicObjectTest.cxx
index 9599fbfeb061..e4709e23db3a 100644
--- a/svtools/qa/unit/GraphicObjectTest.cxx
+++ b/svtools/qa/unit/GraphicObjectTest.cxx
@@ -189,7 +189,7 @@ void GraphicObjectTest::testSizeBasedAutoSwap()
     {
         // First image should be swapped out
         CPPUNIT_ASSERT(pGrafObj1->IsSwappedOut());
-        CPPUNIT_ASSERT_EQUAL(sal_uLong(697230), pGrafObj1->GetSizeBytes());
+        CPPUNIT_ASSERT_EQUAL(sal_uLong(697230), pGrafObj1->GetGraphic().GetSizeBytes());
 
         // Still swapped out: size is cached
         CPPUNIT_ASSERT(pGrafObj1->IsSwappedOut());
@@ -200,7 +200,7 @@ void GraphicObjectTest::testSizeBasedAutoSwap()
         // Size based swap out is triggered by swap in, so the last swapped in image should be
         // in the memory despite of size limit is reached.
         CPPUNIT_ASSERT(!pGrafObj2->IsSwappedOut());
-        CPPUNIT_ASSERT_EQUAL(sal_uLong(1620000), pGrafObj2->GetSizeBytes());
+        CPPUNIT_ASSERT_EQUAL(sal_uLong(1620000), pGrafObj2->GetGraphic().GetSizeBytes());
     }
 
     // Swap in first image -> second image will be swapped out
@@ -220,7 +220,7 @@ void GraphicObjectTest::testSizeBasedAutoSwap()
     // Use bigger cache
     {
         GraphicManager& rGrfMgr = pGrafObj1->GetGraphicManager();
-        rGrfMgr.SetMaxCacheSize((pGrafObj1->GetSizeBytes()+pGrafObj2->GetSizeBytes())*10);
+        rGrfMgr.SetMaxCacheSize((pGrafObj1->GetGraphic().GetSizeBytes()+pGrafObj2->GetGraphic().GetSizeBytes())*10);
     }
     // Swap in both images -> both should be swapped in
     {
@@ -279,7 +279,7 @@ void GraphicObjectTest::testTdf88935()
     // Set cache size
     {
         GraphicManager& rGrfMgr = pGraphObj1->GetGraphicManager();
-        rGrfMgr.SetMaxCacheSize((pGraphObj1->GetSizeBytes()+pGraphObj2->GetSizeBytes())*10);
+        rGrfMgr.SetMaxCacheSize((pGraphObj1->GetGraphic().GetSizeBytes()+pGraphObj2->GetGraphic().GetSizeBytes())*10);
     }
 
     // Both images fit into the cache
diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx
index 2aced9a3227f..0415cfbe3eb2 100644
--- a/svx/source/svdraw/svdograf.cxx
+++ b/svx/source/svdraw/svdograf.cxx
@@ -288,7 +288,7 @@ sdr::contact::ViewContact* SdrGrafObj::CreateObjectSpecificViewContact()
 
 void SdrGrafObj::onGraphicChanged()
 {
-    if (!pGraphic || pGraphic->IsSwappedOut()) // don't force swap-in for this
+    if (!pGraphic || !pGraphic->GetGraphic().isAvailable())
         return;
 
     const SvgDataPtr& rSvgDataPtr = pGraphic->GetGraphic().getSvgData();
@@ -552,12 +552,12 @@ bool SdrGrafObj::IsSwappedOut() const
     return mbIsPreview || pGraphic->IsSwappedOut();
 }
 
-const MapMode& SdrGrafObj::GetGrafPrefMapMode() const
+MapMode SdrGrafObj::GetGrafPrefMapMode() const
 {
     return pGraphic->GetPrefMapMode();
 }
 
-const Size& SdrGrafObj::GetGrafPrefSize() const
+Size SdrGrafObj::GetGrafPrefSize() const
 {
     return pGraphic->GetPrefSize();
 }
@@ -1338,7 +1338,7 @@ IMPL_LINK( SdrGrafObj, ImpSwapHdl, const GraphicObject*, pO, SvStream* )
 
     if( pO->IsInSwapOut() )
     {
-        if( pModel && !mbIsPreview && pModel->IsSwapGraphics() && pGraphic->GetSizeBytes() > 20480 )
+        if( pModel && !mbIsPreview && pModel->IsSwapGraphics() && pGraphic->GetGraphic().GetSizeBytes() > 20480 )
         {
             // test if this object is visualized from someone
             // ## test only if there are VOCs other than the preview renderer
diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx
index 1add678a67b1..53b4f60dbecb 100644
--- a/svx/source/xml/xmlgrhlp.cxx
+++ b/svx/source/xml/xmlgrhlp.cxx
@@ -499,15 +499,20 @@ OUString SvXMLGraphicHelper::ImplGetGraphicMimeType( const OUString& rFileName )
 Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName,
                                              const OUString& rPictureStreamName )
 {
-    Graphic             aGraphic;
+    Graphic aReturnGraphic;
     SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName ) );
-    if( aStream.xStream.is() )
+    if (aStream.xStream.is())
     {
-        std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( aStream.xStream ));
-        GraphicFilter::GetGraphicFilter().ImportGraphic( aGraphic, "", *pStream );
+        GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+        std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(aStream.xStream));
+        Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(*pStream);
+        if (aGraphic)
+            aReturnGraphic = aGraphic;
+        else
+            rGraphicFilter.ImportGraphic(aReturnGraphic, "", *pStream);
     }
 
-    return aGraphic;
+    return aReturnGraphic;
 }
 
 bool SvXMLGraphicHelper::ImplWriteGraphic( const OUString& rPictureStorageName,
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 4f91797c28ad..4fead8219aba 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -186,15 +186,11 @@ void Test::testLinkedGraphicRT()
             {
                 SwGrfNode* pGrfNode = aNodes[nIndex]->GetGrfNode();
                 CPPUNIT_ASSERT(pGrfNode);
-                // RT via DOCX makes linked graphic embedded?!
-                if( aFilterNames[nFilter] != "Office Open XML Text" )
-                {
-                    CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pGrfNode->IsGrfLink());
-                }
+
                 const GraphicObject& rGraphicObj = pGrfNode->GetGrfObj(true);
-                CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), !rGraphicObj.IsSwappedOut());
-                CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphicObj.GetType()));
-                CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), static_cast<sal_uLong>(864900), rGraphicObj.GetSizeBytes());
+                const Graphic& rGraphic = rGraphicObj.GetGraphic();
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(GraphicType::Bitmap), int(rGraphic.GetType()));
+                CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(864900), rGraphic.GetSizeBytes());
                 bImageFound = true;
             }
         }
diff --git a/vcl/inc/graphic/Manager.hxx b/vcl/inc/graphic/Manager.hxx
index 2ef93c420002..aaa4c29f04e4 100644
--- a/vcl/inc/graphic/Manager.hxx
+++ b/vcl/inc/graphic/Manager.hxx
@@ -45,6 +45,8 @@ private:
 
     DECL_LINK(SwapOutTimerHandler, Timer*, void);
 
+    static sal_Int64 getGraphicSizeBytes(const ImpGraphic* pImpGraphic);
+
 public:
     static Manager& get();
 
diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx
index 10d04183f2b1..2383c1a5f53d 100644
--- a/vcl/inc/impgraph.hxx
+++ b/vcl/inc/impgraph.hxx
@@ -27,6 +27,13 @@ struct ImpSwapInfo
 {
     MapMode     maPrefMapMode;
     Size        maPrefSize;
+
+    bool mbIsAnimated;
+    bool mbIsEPS;
+    bool mbIsTransparent;
+    bool mbIsAlpha;
+
+    sal_uInt32 mnAnimationLoopCount;
 };
 
 class OutputDevice;
@@ -38,7 +45,6 @@ class ImpGraphic;
 class ImpGraphic final
 {
     friend class Graphic;
-    friend class GraphicID;
     friend class vcl::graphic::Manager;
 
 private:
@@ -63,6 +69,7 @@ private:
     GraphicExternalLink          maGraphicExternalLink;
 
     std::chrono::high_resolution_clock::time_point maLastUsed;
+    bool mbPrepared;
 
     /// Used with GfxLink and/or PdfData when they store original media
     /// which might be multi-page (PDF, f.e.) and we need to re-render
@@ -81,6 +88,8 @@ public:
     ImpGraphic( const GDIMetaFile& rMtf );
     ~ImpGraphic();
 
+    void ImplSetPrepared();
+
 private:
 
     ImpGraphic&         operator=( const ImpGraphic& rImpGraphic );
@@ -116,6 +125,9 @@ private:
     bool                ImplIsAnimated() const;
     bool                ImplIsEPS() const;
 
+    bool isAvailable() const;
+    bool makeAvailable();
+
     Bitmap              ImplGetBitmap(const GraphicConversionParameters& rParameters) const;
     BitmapEx            ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const;
     /// Gives direct access to the contained BitmapEx.
@@ -185,6 +197,8 @@ private:
     void setPdfData(const std::shared_ptr<css::uno::Sequence<sal_Int8>>& rPdfData);
 
     bool ensureAvailable () const;
+
+    bool loadPrepared();
 };
 
 #endif // INCLUDED_VCL_INC_IMPGRAPH_HXX
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 4a84f683bef7..78f92dd7b79b 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -19,8 +19,10 @@
 
 #include <config_folders.h>
 
+#include <o3tl/make_unique.hxx>
 #include <osl/mutex.hxx>
 #include <comphelper/processfactory.hxx>
+#include <comphelper/threadpool.hxx>
 #include <comphelper/string.hxx>
 #include <ucbhelper/content.hxx>
 #include <cppuhelper/implbase.hxx>
@@ -34,6 +36,7 @@
 #include <vcl/pngwrite.hxx>
 #include <vcl/svgdata.hxx>
 #include <vcl/virdev.hxx>
+#include <impgraph.hxx>
 #include <vcl/svapp.hxx>
 #include <osl/file.hxx>
 #include <vcl/graphicfilter.hxx>
@@ -1324,6 +1327,379 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPat
     return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, nullptr, pExtHeader );
 }
 
+/// Contains a stream and other associated data to import pixels into a
+/// Graphic.
+struct GraphicImportContext
+{
+    /// Pixel data is read from this stream.
+    std::shared_ptr<SvStream> m_pStream;
+    /// The Graphic the import filter gets.
+    std::shared_ptr<Graphic> m_pGraphic;
+    /// Write pixel data using this access.
+    std::unique_ptr<Bitmap::ScopedWriteAccess> m_pAccess;
+    /// Signals if import finished correctly.
+    ErrCode m_nStatus = GRFILTER_FILTERERROR;
+    /// Original graphic format.
+    GfxLinkType m_eLinkType = GfxLinkType::NONE;
+    /// Position of the stream before reading the data.
+    sal_uInt64 m_nStreamBegin = 0;
+    /// Flags for the import filter.
+    GraphicFilterImportFlags m_nImportFlags = GraphicFilterImportFlags::NONE;
+};
+
+/// Graphic import worker that gets executed on a thread.
+class GraphicImportTask : public comphelper::ThreadTask
+{
+    GraphicImportContext& m_rContext;
+public:
+    GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext);
+    void doWork() override;
+    /// Shared code between threaded and non-threaded version.
+    static void doImport(GraphicImportContext& rContext);
+};
+
+GraphicImportTask::GraphicImportTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, GraphicImportContext& rContext)
+    : comphelper::ThreadTask(pTag),
+      m_rContext(rContext)
+{
+}
+
+void GraphicImportTask::doWork()
+{
+    GraphicImportTask::doImport(m_rContext);
+}
+
+void GraphicImportTask::doImport(GraphicImportContext& rContext)
+{
+    if (!ImportJPEG(*rContext.m_pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, rContext.m_pAccess.get()))
+        rContext.m_nStatus = GRFILTER_FILTERERROR;
+    else
+        rContext.m_eLinkType = GfxLinkType::NativeJpg;
+}
+
+void GraphicFilter::ImportGraphics(std::vector< std::shared_ptr<Graphic> >& rGraphics, const std::vector< std::shared_ptr<SvStream> >& rStreams)
+{
+    static bool bThreads = !getenv("VCL_NO_THREAD_IMPORT");
+    std::vector<GraphicImportContext> aContexts;
+    aContexts.reserve(rStreams.size());
+    comphelper::ThreadPool& rSharedPool = comphelper::ThreadPool::getSharedOptimalPool();
+    std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
+
+    for (const auto& pStream : rStreams)
+    {
+        aContexts.emplace_back();
+        GraphicImportContext& rContext = aContexts.back();
+
+        if (pStream)
+        {
+            rContext.m_pStream = pStream;
+            rContext.m_pGraphic = std::make_shared<Graphic>();
+            rContext.m_nStatus = ERRCODE_NONE;
+
+            // Detect the format.
+            ResetLastError();
+            rContext.m_nStreamBegin = pStream->Tell();
+            sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
+            rContext.m_nStatus = ImpTestOrFindFormat(OUString(), *pStream, nFormat);
+            pStream->Seek(rContext.m_nStreamBegin);
+
+            // Import the graphic.
+            if (rContext.m_nStatus == ERRCODE_NONE && !pStream->GetError())
+            {
+                OUString aFilterName = pConfig->GetImportFilterName(nFormat);
+
+                if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
+                {
+                    rContext.m_nImportFlags = GraphicFilterImportFlags::SetLogsizeForJpeg;
+
+                    if (!ImportJPEG( *pStream, *rContext.m_pGraphic, rContext.m_nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr))
+                        rContext.m_nStatus = GRFILTER_FILTERERROR;
+                    else
+                    {
+                        Bitmap& rBitmap = const_cast<Bitmap&>(rContext.m_pGraphic->GetBitmapExRef().GetBitmapRef());
+                        rContext.m_pAccess = o3tl::make_unique<Bitmap::ScopedWriteAccess>(rBitmap);
+                        pStream->Seek(rContext.m_nStreamBegin);
+                        if (bThreads)
+                            rSharedPool.pushTask(new GraphicImportTask(pTag, rContext));
+                        else
+                            GraphicImportTask::doImport(rContext);
+                    }
+                }
+                else
+                    rContext.m_nStatus = GRFILTER_FILTERERROR;
+            }
+        }
+    }
+
+    rSharedPool.waitUntilDone(pTag);
+
+    // Process data after import.
+    for (auto& rContext : aContexts)
+    {
+        rContext.m_pAccess.reset(nullptr);
+
+        if (rContext.m_nStatus == ERRCODE_NONE && (rContext.m_eLinkType != GfxLinkType::NONE) && !rContext.m_pGraphic->GetContext())
+        {
+            std::unique_ptr<sal_uInt8[]> pGraphicContent;
+
+            const sal_uInt64 nStreamEnd = rContext.m_pStream->Tell();
+            sal_Int32 nGraphicContentSize = nStreamEnd - rContext.m_nStreamBegin;
+
+            if (nGraphicContentSize > 0)
+            {
+                try
+                {
+                    pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+                }
+                catch (const std::bad_alloc&)
+                {
+                    rContext.m_nStatus = GRFILTER_TOOBIG;
+                }
+
+                if (rContext.m_nStatus == ERRCODE_NONE)
+                {
+                    rContext.m_pStream->Seek(rContext.m_nStreamBegin);
+                    rContext.m_pStream->ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+                }
+            }
+
+            if (rContext.m_nStatus == ERRCODE_NONE)
+                rContext.m_pGraphic->SetGfxLink(GfxLink(std::move(pGraphicContent), nGraphicContentSize, rContext.m_eLinkType));
+        }
+
+        if (rContext.m_nStatus != ERRCODE_NONE)
+            rContext.m_pGraphic = nullptr;
+
+        rGraphics.push_back(rContext.m_pGraphic);
+    }
+}
+
+Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream)
+{
+    Graphic aGraphic;
+    sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
+    GfxLinkType eLinkType = GfxLinkType::NONE;
+
+    ResetLastError();
+
+    const sal_uLong nStreamBegin = rIStream.Tell();
+
+    rIStream.Seek(nStreamBegin);
+
+    ErrCode nStatus = ImpTestOrFindFormat("", rIStream, nFormat);
+
+    rIStream.Seek(nStreamBegin);
+    const sal_uInt32 nStreamLength(rIStream.Seek(STREAM_SEEK_TO_END) - nStreamBegin);
+
+    OUString aFilterName = pConfig->GetImportFilterName(nFormat);
+    OUString aExternalFilterName = pConfig->GetExternalFilterName(nFormat, false);
+
+    std::unique_ptr<sal_uInt8[]> pGraphicContent;
+    sal_Int32 nGraphicContentSize = 0;
+
+    // read graphic
+    if (pConfig->IsImportInternalFilter(nFormat))
+    {
+        if (aFilterName.equalsIgnoreAsciiCase(IMP_GIF))
+        {
+            eLinkType = GfxLinkType::NativeGif;
+        }
+        else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
+        {
+            vcl::PNGReader aPNGReader(rIStream);
+
+            // check if this PNG contains a GIF chunk!
+            const std::vector<vcl::PNGReader::ChunkData>& rChunkData = aPNGReader.GetChunks();
+            for (auto const& chunk : rChunkData)
+            {
+                // Microsoft Office is storing Animated GIFs in following chunk
+                if (chunk.nType == PMGCHUNG_msOG)
+                {
+                    sal_uInt32 nChunkSize = chunk.aData.size();
+
+                    if (nChunkSize > 11)
+                    {
+                        const std::vector<sal_uInt8>& rData = chunk.aData;
+                        nGraphicContentSize = nChunkSize - 11;
+                        SvMemoryStream aIStrm(const_cast<sal_uInt8*>(&rData[11]), nGraphicContentSize, StreamMode::READ);
+                        pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+                        sal_uInt64 aCurrentPosition = aIStrm.Tell();
+                        aIStrm.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+                        aIStrm.Seek(aCurrentPosition);
+                        eLinkType = GfxLinkType::NativeGif;
+                        break;
+                    }
+                }
+            }
+            if (eLinkType == GfxLinkType::NONE)
+            {
+                eLinkType = GfxLinkType::NativePng;
+            }
+        }
+        else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
+        {
+            eLinkType = GfxLinkType::NativeJpg;
+        }
+        else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG))
+        {
+            bool bOkay(false);
+
+            if (nStreamLength > 0)
+            {
+                std::vector<sal_uInt8> aTwoBytes(2);
+                rIStream.ReadBytes(aTwoBytes.data(), 2);
+                rIStream.Seek(nStreamBegin);
+
+                if (aTwoBytes[0] == 0x1F && aTwoBytes[1] == 0x8B)
+                {
+                    SvMemoryStream aMemStream;
+                    ZCodec aCodec;
+                    long nMemoryLength;
+
+                    aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, false, true);
+                    nMemoryLength = aCodec.Decompress(rIStream, aMemStream);
+                    aCodec.EndCompression();
+
+                    if (!rIStream.GetError() && nMemoryLength >= 0)
+                    {
+                        nGraphicContentSize = nMemoryLength;
+                        pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+
+                        aMemStream.Seek(STREAM_SEEK_TO_BEGIN);
+                        aMemStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+
+                        bOkay = true;
+                    }
+                }
+                else
+                {
+                    nGraphicContentSize = nStreamLength;
+                    pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+                    rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
+
+                    bOkay = true;
+                }
+            }
+
+            if (bOkay)
+            {
+                eLinkType = GfxLinkType::NativeSvg;
+            }
+            else
+            {
+                nStatus = GRFILTER_FILTERERROR;
+            }
+        }
+        else if (aFilterName.equalsIgnoreAsciiCase(IMP_BMP))
+        {
+            eLinkType = GfxLinkType::NativeBmp;
+        }
+        else if (aFilterName.equalsIgnoreAsciiCase(IMP_MOV))
+        {
+            eLinkType = GfxLinkType::NativeMov;
+        }
+        else if (aFilterName.equalsIgnoreAsciiCase(IMP_WMF) ||
+                 aFilterName.equalsIgnoreAsciiCase(IMP_EMF))
+        {
+            nGraphicContentSize = nStreamLength;
+            pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+
+            rIStream.ReadBytes(pGraphicContent.get(), nStreamLength);
+
+            if (!rIStream.GetError())
+            {
+                eLinkType = GfxLinkType::NativeWmf;
+            }
+            else
+            {
+                nStatus = GRFILTER_FILTERERROR;
+            }
+        }
+        else if (aFilterName == IMP_PDF)
+        {
+            eLinkType = GfxLinkType::NativePdf;
+        }
+        else
+        {
+            nStatus = GRFILTER_FILTERERROR;
+        }
+    }
+    else
+    {
+        ImpFilterLibCacheEntry* pFilter = nullptr;
+
+        // find first filter in filter paths
+        sal_Int32 i, nTokenCount = getTokenCount(aFilterPath, ';');
+        ImpFilterLibCache &rCache = Cache::get();
+        for( i = 0; ( i < nTokenCount ) && ( pFilter == nullptr ); i++ )
+            pFilter = rCache.GetFilter(aFilterPath.getToken(i, ';'), aFilterName, aExternalFilterName);
+            nStatus = GRFILTER_FILTERERROR;
+        if( !pFilter )
+            nStatus = GRFILTER_FILTERERROR;
+        else
+        {
+            PFilterCall pFunc = pFilter->GetImportFunction();
+
+            if (!pFunc)
+                nStatus = GRFILTER_FILTERERROR;
+            else
+            {
+                OUString aShortName;
+                if (nFormat != GRFILTER_FORMAT_DONTKNOW)
+                    aShortName = GetImportFormatShortName(nFormat).toAsciiUpperCase();
+
+                if (aShortName.startsWith(TIF_SHORTNAME))
+                    eLinkType = GfxLinkType::NativeTif;
+                else if( aShortName.startsWith(MET_SHORTNAME))
+                    eLinkType = GfxLinkType::NativeMet;
+                else if( aShortName.startsWith(PCT_SHORTNAME))
+                    eLinkType = GfxLinkType::NativePct;
+            }
+        }
+    }
+
+    if (nStatus == ERRCODE_NONE && eLinkType != GfxLinkType::NONE)
+    {
+        if (!pGraphicContent)
+        {
+            nGraphicContentSize = nStreamLength;
+
+            if (nGraphicContentSize > 0)
+            {
+                try
+                {
+                    pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
+                }
+                catch (const std::bad_alloc&)
+                {
+                    nStatus = GRFILTER_TOOBIG;
+                }
+
+                if (nStatus == ERRCODE_NONE)
+                {
+                    rIStream.Seek(nStreamBegin);
+                    rIStream.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
+                }
+            }
+        }
+
+        if( nStatus == ERRCODE_NONE )
+        {
+            aGraphic.SetGfxLink(GfxLink(std::move(pGraphicContent), nGraphicContentSize, eLinkType));
+            aGraphic.ImplGetImpGraphic()->ImplSetPrepared();
+        }
+    }
+
+    // Set error code or try to set native buffer
+    if(nStatus != ERRCODE_NONE)
+    {
+        ImplSetError(nStatus, &rIStream);
+        rIStream.Seek(nStreamBegin);
+    }
+
+    return aGraphic;
+}
+
 sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPath, SvStream& rIStream,
                                      sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags,
                                      css::uno::Sequence< css::beans::PropertyValue >* pFilterData,
@@ -2182,17 +2558,18 @@ IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
     OString aShortName;
     switch( rData.mnFormat )
     {
-        case( ConvertDataFormat::BMP ): aShortName = BMP_SHORTNAME; break;
-        case( ConvertDataFormat::GIF ): aShortName = GIF_SHORTNAME; break;
-        case( ConvertDataFormat::JPG ): aShortName = JPG_SHORTNAME; break;
-        case( ConvertDataFormat::MET ): aShortName = MET_SHORTNAME; break;
-        case( ConvertDataFormat::PCT ): aShortName = PCT_SHORTNAME; break;
-        case( ConvertDataFormat::PNG ): aShortName = PNG_SHORTNAME; break;
-        case( ConvertDataFormat::SVM ): aShortName = SVM_SHORTNAME; break;
-        case( ConvertDataFormat::TIF ): aShortName = TIF_SHORTNAME; break;
-        case( ConvertDataFormat::WMF ): aShortName = WMF_SHORTNAME; break;
-        case( ConvertDataFormat::EMF ): aShortName = EMF_SHORTNAME; break;
-        case( ConvertDataFormat::SVG ): aShortName = SVG_SHORTNAME; break;
+        case ConvertDataFormat::BMP: aShortName = BMP_SHORTNAME; break;
+        case ConvertDataFormat::GIF: aShortName = GIF_SHORTNAME; break;
+        case ConvertDataFormat::JPG: aShortName = JPG_SHORTNAME; break;
+        case ConvertDataFormat::MET: aShortName = MET_SHORTNAME; break;
+        case ConvertDataFormat::PCT: aShortName = PCT_SHORTNAME; break;
+        case ConvertDataFormat::PNG: aShortName = PNG_SHORTNAME; break;
+        case ConvertDataFormat::SVM: aShortName = SVM_SHORTNAME; break;
+        case ConvertDataFormat::TIF: aShortName = TIF_SHORTNAME; break;
+        case ConvertDataFormat::WMF: aShortName = WMF_SHORTNAME; break;
+        case ConvertDataFormat::EMF: aShortName = EMF_SHORTNAME; break;
+        case ConvertDataFormat::SVG: aShortName = SVG_SHORTNAME; break;
+        case ConvertDataFormat::PDF: aShortName = PDF_SHORTNAME; break;
 
         default:
         break;
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
index 8f7c3708f28a..798ef5e8a00c 100644
--- a/vcl/source/gdi/gfxlink.cxx
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -27,22 +27,28 @@
 #include <vcl/graph.hxx>
 #include <vcl/gfxlink.hxx>
 #include <vcl/cvtgrf.hxx>
-#include <com/sun/star/ucb/CommandAbortedException.hpp>
+#include <vcl/graphicfilter.hxx>
 #include <memory>
 #include <o3tl/make_shared.hxx>
 
 GfxLink::GfxLink()
+    : meType(GfxLinkType::NONE)
+    , mnUserId(0)
+    , mnSwapInDataSize(0)
+    , mbPrefMapModeValid(false)
+    , mbPrefSizeValid(false)
 {
 }
 
-GfxLink::GfxLink( std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nSize, GfxLinkType nType )
+GfxLink::GfxLink(std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nSize, GfxLinkType nType)
+    : meType(nType)
+    , mnUserId(0)
+    , mpSwapInData(std::shared_ptr<sal_uInt8>(pBuf.release(), pBuf.get_deleter())) // std::move(pBuf) does not compile on Jenkins MacOSX (24 May 2016)
+    , mnSwapInDataSize(nSize)
+    , mbPrefMapModeValid(false)
+    , mbPrefSizeValid(false)
 {
-    SAL_WARN_IF( pBuf == nullptr || !nSize, "vcl",
-                "GfxLink::GfxLink(): empty/NULL buffer given" );
-
-    meType = nType;
-    mnSwapInDataSize = nSize;
-    mpSwapInData = std::shared_ptr<sal_uInt8>(pBuf.release(), pBuf.get_deleter());  // std::move(pBuf) does not compile on Jenkins MacOSX (24 May 2016)
+    SAL_WARN_IF(mpSwapInData.get() == nullptr || mnSwapInDataSize <= 0, "vcl", "GfxLink::GfxLink(): empty/NULL buffer given");
 }
 
 bool GfxLink::operator==( const GfxLink& rGfxLink ) const
@@ -102,31 +108,33 @@ bool GfxLink::LoadNative( Graphic& rGraphic )
     if( IsNative() && mnSwapInDataSize )
     {
         const sal_uInt8* pData = GetData();
-
-        if( pData )
+        if (pData)
         {
-            SvMemoryStream    aMemStm;
-            ConvertDataFormat nCvtType;
-
-            aMemStm.SetBuffer( const_cast<sal_uInt8*>(pData), mnSwapInDataSize, mnSwapInDataSize );
+            SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(pData), mnSwapInDataSize, StreamMode::READ | StreamMode::WRITE);
+            OUString aShortName;
 
-            switch( meType )
+            switch (meType)
             {
-                case GfxLinkType::NativeGif: nCvtType = ConvertDataFormat::GIF; break;
-                case GfxLinkType::NativeBmp: nCvtType = ConvertDataFormat::BMP; break;
-                case GfxLinkType::NativeJpg: nCvtType = ConvertDataFormat::JPG; break;
-                case GfxLinkType::NativePng: nCvtType = ConvertDataFormat::PNG; break;
-                case GfxLinkType::NativeTif: nCvtType = ConvertDataFormat::TIF; break;
-                case GfxLinkType::NativeWmf: nCvtType = ConvertDataFormat::WMF; break;
-                case GfxLinkType::NativeMet: nCvtType = ConvertDataFormat::MET; break;
-                case GfxLinkType::NativePct: nCvtType = ConvertDataFormat::PCT; break;
-                case GfxLinkType::NativeSvg: nCvtType = ConvertDataFormat::SVG; break;
-
-                default: nCvtType = ConvertDataFormat::Unknown; break;
+                case GfxLinkType::NativeGif: aShortName = GIF_SHORTNAME; break;
+                case GfxLinkType::NativeJpg: aShortName = JPG_SHORTNAME; break;
+                case GfxLinkType::NativePng: aShortName = PNG_SHORTNAME; break;
+                case GfxLinkType::NativeTif: aShortName = TIF_SHORTNAME; break;
+                case GfxLinkType::NativeWmf: aShortName = WMF_SHORTNAME; break;
+                case GfxLinkType::NativeMet: aShortName = MET_SHORTNAME; break;
+                case GfxLinkType::NativePct: aShortName = PCT_SHORTNAME; break;
+                case GfxLinkType::NativeSvg: aShortName = SVG_SHORTNAME; break;
+                case GfxLinkType::NativeBmp: aShortName = BMP_SHORTNAME; break;
+                case GfxLinkType::NativePdf: aShortName = PDF_SHORTNAME; break;
+                default: break;
+            }
+            if (!aShortName.isEmpty())
+            {
+                GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+                sal_uInt16 nFormat = rFilter.GetImportFormatNumberForShortName(aShortName);
+                ErrCode nResult = rFilter.ImportGraphic(rGraphic, OUString(), aMemoryStream, nFormat);
+                if (nResult == ERRCODE_NONE)
+                    bRet = true;
             }
-
-            if( nCvtType != ConvertDataFormat::Unknown && ( GraphicConverter::Import( aMemStm, rGraphic, nCvtType ) == ERRCODE_NONE ) )
-                bRet = true;
         }
     }
 
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index d22a29779d8b..dfb091362ec9 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -253,6 +253,16 @@ void Graphic::ImplTestRefCount()
     }
 }
 
+bool Graphic::isAvailable() const
+{
+    return mxImpGraphic->isAvailable();
+}
+
+bool Graphic::makeAvailable()
+{
+    return mxImpGraphic->makeAvailable();
+}
+
 Graphic& Graphic::operator=( const Graphic& rGraphic )
 {
     if( &rGraphic != this )
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 64b5bab9ac75..798022e8f9f4 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -30,6 +30,7 @@
 #include <unotools/ucbstreamhelper.hxx>
 #include <unotools/tempfile.hxx>
 #include <vcl/outdev.hxx>
+#include <vcl/graphicfilter.hxx>
 #include <vcl/virdev.hxx>
 #include <vcl/gfxlink.hxx>
 #include <vcl/cvtgrf.hxx>
@@ -106,6 +107,7 @@ ImpGraphic::ImpGraphic() :
         mbSwapOut       ( false ),
         mbDummyContext  ( false ),
         maLastUsed (std::chrono::high_resolution_clock::now()),
+        mbPrepared      ( false ),
         mnPageNumber(-1)
 {
 }
@@ -124,6 +126,7 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic)
     , mpPdfData(rImpGraphic.mpPdfData)
     , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
     , maLastUsed (std::chrono::high_resolution_clock::now())
+    , mbPrepared (rImpGraphic.mbPrepared)
     , mnPageNumber(rImpGraphic.mnPageNumber)
 {
     if( rImpGraphic.mpGfxLink )
@@ -152,12 +155,25 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic)
     , mpPdfData(std::move(rImpGraphic.mpPdfData))
     , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
     , maLastUsed (std::chrono::high_resolution_clock::now())
+    , mbPrepared (rImpGraphic.mbPrepared)
     , mnPageNumber(rImpGraphic.mnPageNumber)
 {
     rImpGraphic.ImplClear();
     rImpGraphic.mbDummyContext = false;
 }
 
+ImpGraphic::ImpGraphic(GraphicExternalLink const & rGraphicExternalLink) :
+        meType          ( GraphicType::Default ),
+        mnSizeBytes     ( 0 ),
+        mbSwapOut       ( false ),
+        mbDummyContext  ( false ),
+        maGraphicExternalLink(rGraphicExternalLink),
+        maLastUsed (std::chrono::high_resolution_clock::now()),
+        mbPrepared (false),
+        mnPageNumber(-1)
+{
+}
+
 ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
         maEx            ( rBitmap ),
         meType          ( !rBitmap.IsEmpty() ? GraphicType::Bitmap : GraphicType::NONE ),
@@ -165,6 +181,7 @@ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
         mbSwapOut       ( false ),
         mbDummyContext  ( false ),
         maLastUsed (std::chrono::high_resolution_clock::now()),
+        mbPrepared (false),
         mnPageNumber(-1)
 {
 }
@@ -176,6 +193,7 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
         mbSwapOut       ( false ),
         mbDummyContext  ( false ),
         maLastUsed (std::chrono::high_resolution_clock::now()),
+        mbPrepared (false),
         mnPageNumber(-1)
 {
 }
@@ -187,6 +205,7 @@ ImpGraphic::ImpGraphic(const SvgDataPtr& rSvgDataPtr)
     mbDummyContext  ( false ),
     maSvgData(rSvgDataPtr),
     maLastUsed (std::chrono::high_resolution_clock::now()),
+    mbPrepared (false),
     mnPageNumber(-1)
 {
 }
@@ -199,6 +218,7 @@ ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
         mbSwapOut       ( false ),
         mbDummyContext  ( false ),
         maLastUsed (std::chrono::high_resolution_clock::now()),
+        mbPrepared (false),
         mnPageNumber(-1)
 {
 }
@@ -210,6 +230,7 @@ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
         mbSwapOut       ( false ),
         mbDummyContext  ( false ),
         maLastUsed (std::chrono::high_resolution_clock::now()),
+        mbPrepared (false),
         mnPageNumber(-1)
 {
 }
@@ -249,6 +270,7 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
 
         mbSwapOut = rImpGraphic.mbSwapOut;
         mpSwapFile = rImpGraphic.mpSwapFile;
+        mbPrepared = rImpGraphic.mbPrepared;
 
         mpGfxLink.reset();
 
@@ -284,6 +306,7 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic)
     maSvgData = std::move(rImpGraphic.maSvgData);
     mpPdfData = std::move(rImpGraphic.mpPdfData);
     maGraphicExternalLink = rImpGraphic.maGraphicExternalLink;
+    mbPrepared = rImpGraphic.mbPrepared;
 
     rImpGraphic.ImplClear();
     rImpGraphic.mbDummyContext = false;
@@ -302,7 +325,11 @@ bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const
 
     if( this == &rImpGraphic )
         bRet = true;
-    else if( !ImplIsSwapOut() && ( rImpGraphic.meType == meType ) )
+    else if (mbPrepared && rImpGraphic.mbPrepared)
+    {
+        bRet = (*mpGfxLink == *rImpGraphic.mpGfxLink);
+    }
+    else if (isAvailable() && rImpGraphic.isAvailable())
     {
         switch( meType )
         {
@@ -379,6 +406,11 @@ void ImpGraphic::ImplCreateSwapInfo()
     {
         maSwapInfo.maPrefMapMode = ImplGetPrefMapMode();
         maSwapInfo.maPrefSize = ImplGetPrefSize();
+        maSwapInfo.mbIsAnimated = ImplIsAnimated();
+        maSwapInfo.mbIsEPS = ImplIsEPS();
+        maSwapInfo.mbIsTransparent = ImplIsTransparent();
+        maSwapInfo.mbIsAlpha = ImplIsAlpha();
+        maSwapInfo.mnAnimationLoopCount = ImplGetAnimationLoopCount();
     }
 }
 
@@ -416,10 +448,37 @@ ImpSwapFile::~ImpSwapFile()
     }
 }
 
+void ImpGraphic::ImplSetPrepared()
+{
+    mbPrepared = true;
+    mbSwapOut = true;
+    meType = GraphicType::Bitmap;
+
+    SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(mpGfxLink->GetData()), mpGfxLink->GetDataSize(), StreamMode::READ | StreamMode::WRITE);
+
+    GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+    if (aDescriptor.Detect(true))
+    {
+        maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
+        maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
+    }
+    maSwapInfo.mnAnimationLoopCount = 0;
+    maSwapInfo.mbIsAnimated = false;
+    maSwapInfo.mbIsEPS = false;
+    maSwapInfo.mbIsTransparent = false;
+    maSwapInfo.mbIsAlpha = false;
+
+    if (mpGfxLink->GetType() == GfxLinkType::NativeGif)
+    {
+        maSwapInfo.mbIsAnimated = true;
+    }
+}
+
 void ImpGraphic::ImplClear()
 {
     mpSwapFile.reset();
     mbSwapOut = false;
+    mbPrepared = false;
 
     // cleanup
     ImplClearGraphics();
@@ -445,11 +504,13 @@ bool ImpGraphic::ImplIsTransparent() const
 {
     bool bRet(true);
 
-    ensureAvailable();
-
-    if( meType == GraphicType::Bitmap && !maSvgData.get())
+    if (mbSwapOut)
     {
-        bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() );
+        bRet = maSwapInfo.mbIsTransparent;
+    }
+    else if (meType == GraphicType::Bitmap && !maSvgData.get())
+    {
+        bRet = mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent();
     }
 
     return bRet;
@@ -459,15 +520,17 @@ bool ImpGraphic::ImplIsAlpha() const
 {
     bool bRet(false);
 
-    ensureAvailable();
-
-    if(maSvgData.get())
+    if (mbSwapOut)
+    {
+        bRet = maSwapInfo.mbIsAlpha;
+    }
+    else if (maSvgData.get())
     {
         bRet = true;
     }
-    else if( meType == GraphicType::Bitmap )
+    else if (meType == GraphicType::Bitmap)
     {
-        bRet = ( nullptr == mpAnimation ) && maEx.IsAlpha();
+        bRet = (nullptr == mpAnimation && maEx.IsAlpha());
     }
 
     return bRet;
@@ -475,19 +538,29 @@ bool ImpGraphic::ImplIsAlpha() const
 
 bool ImpGraphic::ImplIsAnimated() const
 {
-    ensureAvailable();
-    return( mpAnimation != nullptr );
+    return mbSwapOut ? maSwapInfo.mbIsAnimated : mpAnimation != nullptr;
 }
 
 bool ImpGraphic::ImplIsEPS() const
 {
-    ensureAvailable();
+    if (mbSwapOut)
+        return maSwapInfo.mbIsEPS;
 
     return( ( meType == GraphicType::GdiMetafile ) &&
             ( maMetaFile.GetActionSize() > 0 ) &&
             ( maMetaFile.GetAction( 0 )->GetType() == MetaActionType::EPS ) );
 }
 
+bool ImpGraphic::isAvailable() const
+{
+    return !mbPrepared && !mbSwapOut;
+}
+
+bool ImpGraphic::makeAvailable()
+{
+    return ensureAvailable();
+}
+
 Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
 {
     Bitmap aRetBmp;
@@ -697,8 +770,10 @@ Size ImpGraphic::ImplGetPrefSize() const
 {
     Size aSize;
 
-    if( ImplIsSwapOut() )
+    if (ImplIsSwapOut())
+    {
         aSize = maSwapInfo.maPrefSize;
+    }
     else
     {
         switch( meType )
@@ -742,6 +817,8 @@ Size ImpGraphic::ImplGetPrefSize() const
 
 void ImpGraphic::ImplSetPrefSize( const Size& rPrefSize )
 {
+    ensureAvailable();
+
     switch( meType )
     {
         case GraphicType::NONE:
@@ -782,8 +859,10 @@ MapMode ImpGraphic::ImplGetPrefMapMode() const
 {
     MapMode aMapMode;
 
-    if( ImplIsSwapOut() )
+    if (ImplIsSwapOut())
+    {
         aMapMode = maSwapInfo.maPrefMapMode;
+    }
     else
     {
         switch( meType )
@@ -823,6 +902,8 @@ MapMode ImpGraphic::ImplGetPrefMapMode() const
 
 void ImpGraphic::ImplSetPrefMapMode( const MapMode& rPrefMapMode )
 {
+    ensureAvailable();
+
     switch( meType )
     {
         case GraphicType::NONE:
@@ -863,6 +944,9 @@ sal_uLong ImpGraphic::ImplGetSizeBytes() const
 {
     if( 0 == mnSizeBytes )
     {
+        if (mbPrepared)
+            ensureAvailable();
+
         if( meType == GraphicType::Bitmap )
         {
             if(maSvgData.get())
@@ -977,12 +1061,16 @@ void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt
 
 void ImpGraphic::ImplStopAnimation( OutputDevice* pOutDev, long nExtraData )
 {
+    ensureAvailable();
+
     if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation )
         mpAnimation->Stop( pOutDev, nExtraData );
 }
 
 void ImpGraphic::ImplSetAnimationNotifyHdl( const Link<Animation*,void>& rLink )
 {
+    ensureAvailable();
+
     if( mpAnimation )
         mpAnimation->SetNotifyHdl( rLink );
 }
@@ -991,6 +1079,8 @@ Link<Animation*,void> ImpGraphic::ImplGetAnimationNotifyHdl() const
 {
     Link<Animation*,void> aLink;
 
+    ensureAvailable();
+
     if( mpAnimation )
         aLink = mpAnimation->GetNotifyHdl();
 
@@ -999,8 +1089,10 @@ Link<Animation*,void> ImpGraphic::ImplGetAnimationNotifyHdl() const
 
 sal_uInt32 ImpGraphic::ImplGetAnimationLoopCount() const
 {
-    ensureAvailable();
-    return( mpAnimation ? mpAnimation->GetLoopCount() : 0 );
+    if (mbSwapOut)
+        return maSwapInfo.mnAnimationLoopCount;
+
+    return mpAnimation ? mpAnimation->GetLoopCount() : 0;
 }
 
 void ImpGraphic::ImplSetContext( const std::shared_ptr<GraphicReader>& pReader )
@@ -1011,6 +1103,8 @@ void ImpGraphic::ImplSetContext( const std::shared_ptr<GraphicReader>& pReader )
 
 bool ImpGraphic::ImplReadEmbedded( SvStream& rIStm )
 {
+    ensureAvailable();
+
     MapMode         aMapMode;
     Size            aSize;
     sal_uInt32      nId;
@@ -1318,17 +1412,37 @@ bool ImpGraphic::ImplSwapOut( SvStream* xOStm )
 bool ImpGraphic::ensureAvailable() const
 {
     auto pThis = const_cast<ImpGraphic*>(this);
-    pThis->maLastUsed = std::chrono::high_resolution_clock::now();
+
     if (ImplIsSwapOut())
         return pThis->ImplSwapIn();
+
+    pThis->maLastUsed = std::chrono::high_resolution_clock::now();
     return true;
 }
 
+bool ImpGraphic::loadPrepared()
+{
+    Graphic aGraphic;
+    if (mpGfxLink->LoadNative(aGraphic))
+    {
+        *this = *aGraphic.ImplGetImpGraphic();
+        return true;
+    }
+    return false;
+}
+
 bool ImpGraphic::ImplSwapIn()
 {
     bool bRet = false;
 
-    if( ImplIsSwapOut() )
+    if (!ImplIsSwapOut())
+        return bRet;
+
+    if (mbPrepared)
+    {
+        bRet = loadPrepared();
+    }
+    else
     {
         OUString aSwapURL;
 
@@ -1675,6 +1789,8 @@ SvStream& WriteImpGraphic( SvStream& rOStm, const ImpGraphic& rImpGraphic )
     if (rOStm.GetError())
         return rOStm;
 
+    rImpGraphic.ensureAvailable();
+
     if (rImpGraphic.ImplIsSwapOut())
     {
         rOStm.SetError( SVSTREAM_GENERALERROR );
diff --git a/vcl/source/graphic/GraphicObject.cxx b/vcl/source/graphic/GraphicObject.cxx
index 67ef8a7b249b..444a5a26cf24 100644
--- a/vcl/source/graphic/GraphicObject.cxx
+++ b/vcl/source/graphic/GraphicObject.cxx
@@ -140,7 +140,7 @@ void GraphicObject::ImplAssignGraphicData()
     mnSizeBytes = maGraphic.GetSizeBytes();
     meType = maGraphic.GetType();
     mbTransparent = maGraphic.IsTransparent();
-    mbAlpha = maGraphic.IsAlpha();
+    // mbAlpha = maGraphic.IsAlpha();
     mbAnimated = maGraphic.IsAnimated();
     mbEPS = maGraphic.IsEPS();
     mnAnimationLoopCount = ( mbAnimated ? maGraphic.GetAnimationLoopCount() : 0 );
@@ -234,7 +234,37 @@ void GraphicObject::ImplAutoSwapIn()
     }
 }
 
-bool GraphicObject::ImplGetCropParams( OutputDevice* pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
+GraphicType GraphicObject::GetType() const
+{
+    return maGraphic.GetType();
+}
+
+Size GraphicObject::GetPrefSize() const
+{
+    return maGraphic.GetPrefSize();
+}
+
+MapMode GraphicObject::GetPrefMapMode() const
+{
+    return maGraphic.GetPrefMapMode();
+}
+
+bool GraphicObject::IsTransparent() const
+{
+    return maGraphic.IsTransparent();
+}
+
+bool GraphicObject::IsAnimated() const
+{
+    return maGraphic.IsAnimated();
+}
+
+bool GraphicObject::IsEPS() const
+{
+    return maGraphic.IsEPS();
+}
+
+bool GraphicObject::ImplGetCropParams( OutputDevice * pOut, Point& rPt, Size& rSz, const GraphicAttr* pAttr,
                                        tools::PolyPolygon& rClipPolyPoly, bool& bRectClipRegion ) const
 {
     bool bRet = false;
@@ -316,7 +346,6 @@ GraphicObject& GraphicObject::operator=( const GraphicObject& rGraphicObj )
         maAttr = rGraphicObj.maAttr;
         maLink = rGraphicObj.maLink;
         maUserData = rGraphicObj.maUserData;
-        ImplAssignGraphicData();
         mbAutoSwapped = false;
         mpGlobalMgr->ImplRegisterObj( *this, maGraphic, nullptr, &rGraphicObj );
         if( rGraphicObj.HasUserData() && rGraphicObj.IsSwappedOut() )
@@ -633,7 +662,6 @@ void GraphicObject::SetGraphic( const Graphic& rGraphic, const GraphicObject* pC
 
     maGraphic = rGraphic;
     mbAutoSwapped = false;
-    ImplAssignGraphicData();
     maLink.clear();
     mxSimpleCache.reset();
 
@@ -920,7 +948,7 @@ Graphic GraphicObject::GetTransformedGraphic( const GraphicAttr* pAttr ) const /
             if( ( GetType() == GraphicType::Bitmap ) && IsAnimated() )
             {
                 Animation aAnimation( maGraphic.GetAnimation() );
-                aAnimation.SetLoopCount( mnAnimationLoopCount );
+                aAnimation.SetLoopCount(maGraphic.GetAnimationLoopCount());
                 aGraphic = aAnimation;
             }
             else
diff --git a/vcl/source/graphic/GraphicObject2.cxx b/vcl/source/graphic/GraphicObject2.cxx
index 4fa85ee9d85a..87122f5af02d 100644
--- a/vcl/source/graphic/GraphicObject2.cxx
+++ b/vcl/source/graphic/GraphicObject2.cxx
@@ -165,8 +165,8 @@ void GraphicManager::ImplUnregisterObj( const GraphicObject& rObj )
 void GraphicManager::ImplGraphicObjectWasSwappedOut( const GraphicObject& rObj )
 {
     mpCache->GraphicObjectWasSwappedOut( rObj );
-    assert(mnUsedSize >= rObj.GetSizeBytes());
-    mnUsedSize -= rObj.GetSizeBytes();
+    assert(mnUsedSize >= rObj.GetGraphic().GetSizeBytes());
+    mnUsedSize -= rObj.GetGraphic().GetSizeBytes();
 }
 
 OString GraphicManager::ImplGetUniqueID( const GraphicObject& rObj ) const
@@ -215,7 +215,7 @@ void GraphicManager::ImplCheckSizeOfSwappedInGraphics(const GraphicObject* pGrap
             }
 
             // do not swap out when we have less than 16KB data objects
-            if(pObj->GetSizeBytes() >= (16 * 1024))
+            if(pObj->GetGraphic().GetSizeBytes() >= (16 * 1024))
             {
                 pObj->FireSwapOutRequest();
             }
diff --git a/vcl/source/graphic/Manager.cxx b/vcl/source/graphic/Manager.cxx
index be8343fa664a..7a959577313f 100644
--- a/vcl/source/graphic/Manager.cxx
+++ b/vcl/source/graphic/Manager.cxx
@@ -68,7 +68,7 @@ void Manager::reduceGraphicMemory()
         if (mnUsedSize < mnTotalCacheSize * 0.7)
             return;
 
-        sal_Int64 nCurrentGraphicSize = pEachImpGraphic->ImplGetSizeBytes();
+        sal_Int64 nCurrentGraphicSize = getGraphicSizeBytes(pEachImpGraphic);
         if (!pEachImpGraphic->ImplIsSwapOut() && nCurrentGraphicSize > 1000000)
         {
             if (!pEachImpGraphic->mpContext)
@@ -84,6 +84,13 @@ void Manager::reduceGraphicMemory()
     }
 }
 
+sal_Int64 Manager::getGraphicSizeBytes(const ImpGraphic* pImpGraphic)
+{
+    if (!pImpGraphic->isAvailable())
+        return 0;
+    return pImpGraphic->ImplGetSizeBytes();
+}
+
 IMPL_LINK(Manager, SwapOutTimerHandler, Timer*, pTimer, void)
 {
     pTimer->Stop();
@@ -99,7 +106,7 @@ void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic,
         reduceGraphicMemory();
 
     // Insert and update the used size (bytes)
-    mnUsedSize += pImpGraphic->ImplGetSizeBytes();
+    mnUsedSize += getGraphicSizeBytes(pImpGraphic.get());
     m_pImpGraphicList.insert(pImpGraphic.get());
 
     // calculate size of the graphic set
@@ -108,7 +115,7 @@ void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic,
     {
         if (!pEachImpGraphic->ImplIsSwapOut())
         {
-            calculatedSize += pEachImpGraphic->ImplGetSizeBytes();
+            calculatedSize += getGraphicSizeBytes(pEachImpGraphic);
         }
     }
 
@@ -123,7 +130,7 @@ void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic,
 
 void Manager::unregisterGraphic(ImpGraphic* pImpGraphic)
 {
-    mnUsedSize -= pImpGraphic->ImplGetSizeBytes();
+    mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
     m_pImpGraphicList.erase(pImpGraphic);
 }
 
@@ -178,18 +185,18 @@ std::shared_ptr<ImpGraphic> Manager::newInstance(const GDIMetaFile& rMetaFile)
 
 void Manager::swappedIn(const ImpGraphic* pImpGraphic)
 {
-    mnUsedSize += pImpGraphic->ImplGetSizeBytes();
+    mnUsedSize += getGraphicSizeBytes(pImpGraphic);
 }
 
 void Manager::swappedOut(const ImpGraphic* pImpGraphic)
 {
-    mnUsedSize -= pImpGraphic->ImplGetSizeBytes();
+    mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
 }
 
 void Manager::changeExisting(const ImpGraphic* pImpGraphic, sal_Int64 nOldSizeBytes)
 {
     mnUsedSize -= nOldSizeBytes;
-    mnUsedSize += pImpGraphic->ImplGetSizeBytes();
+    mnUsedSize += getGraphicSizeBytes(pImpGraphic);
 }
 }
 } // end vcl::graphic
commit 91703dfbca37734d2da2fa794503bc227a36d353
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon May 8 16:52:00 2017 +0200

    vcl: split jpeg import into two parts
    
    Split the import into two:
    
    1) Just create the bitmap, this part is not thread-safe (e.g.
    OpenGLContext::makeCurrent() is called when OpenGL is enabled).
    
    2) Import the image into an existing bitmap.
    
    The point is that the second part takes much more time than the first,
    and in the future that part may be executed on a thread, while without
    such a split the whole ImportJPEG() can't do that. For now
    GraphicFilter::ImportGraphic() simply invokes the two parts after each
    other, so no real functional changes yet.
    
    Reviewed-on: https://gerrit.libreoffice.org/37397
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>
    (cherry picked from commit e8a05109d91bb9e82fcec5204514766f4bdbbee8)
    
    Change-Id: Iee742a2cd3c581aeaf1a1ed9f55cd543955a85e0

diff --git a/include/vcl/bitmapex.hxx b/include/vcl/bitmapex.hxx
index 3d6a04eefc1e..ab68620fd76f 100644
--- a/include/vcl/bitmapex.hxx
+++ b/include/vcl/bitmapex.hxx
@@ -72,6 +72,8 @@ public:
     TransparentType     GetTransparentType() const { return eTransparent; }
 
     Bitmap              GetBitmap( const Color* pTransReplaceColor = nullptr ) const;
+    /// Gives direct access to the contained bitmap.
+    const Bitmap&       GetBitmapRef() const;
     Bitmap              GetMask() const;
 
     bool                IsAlpha() const;
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index 7aec891e05ff..1676b883c4d6 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -148,6 +148,8 @@ public:
     // before.
     Bitmap          GetBitmap(const GraphicConversionParameters& rParameters = GraphicConversionParameters()) const;
     BitmapEx        GetBitmapEx(const GraphicConversionParameters& rParameters = GraphicConversionParameters()) const;
+    /// Gives direct access to the contained BitmapEx.
+    const BitmapEx& GetBitmapExRef() const;
 
     Animation       GetAnimation() const;
     const GDIMetaFile& GetGDIMetaFile() const;
diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index c0bbb3d62a77..8b8a7cef3008 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -56,10 +56,14 @@ enum class GraphicFilterImportFlags
     DontSetLogsizeForJpeg  = 0x002,
     ForPreview             = 0x004,
     AllowPartialStreamRead = 0x010,
+    /// Only create a bitmap, do not read pixel data.
+    OnlyCreateBitmap       = 0x020,
+    /// Read pixel data into an existing bitmap.
+    UseExistingBitmap      = 0x040,
 };
 namespace o3tl
 {
-    template<> struct typed_flags<GraphicFilterImportFlags> : is_typed_flags<GraphicFilterImportFlags, 0x0017> {};
+    template<> struct typed_flags<GraphicFilterImportFlags> : is_typed_flags<GraphicFilterImportFlags, 0x0077> {};
 }
 
 #define IMP_BMP                 "SVBMP"
diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx
index bba9b9708d1e..10d04183f2b1 100644
--- a/vcl/inc/impgraph.hxx
+++ b/vcl/inc/impgraph.hxx
@@ -118,6 +118,8 @@ private:
 
     Bitmap              ImplGetBitmap(const GraphicConversionParameters& rParameters) const;
     BitmapEx            ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const;
+    /// Gives direct access to the contained BitmapEx.
+    const BitmapEx&     ImplGetBitmapExRef() const;
     Animation           ImplGetAnimation() const;
     const GDIMetaFile&  ImplGetGDIMetaFile() const;
 
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 8b57c8085b26..4a84f683bef7 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -1501,10 +1501,19 @@ sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const OUString& rPat
             if( !( nImportFlags & GraphicFilterImportFlags::DontSetLogsizeForJpeg ) )
                 nImportFlags |= GraphicFilterImportFlags::SetLogsizeForJpeg;
 
-            if( !ImportJPEG( rIStream, rGraphic, nImportFlags ) )
+            sal_uInt64 nPosition = rIStream.Tell();
+            if( !ImportJPEG( rIStream, rGraphic, nImportFlags | GraphicFilterImportFlags::OnlyCreateBitmap, nullptr ) )
                 nStatus = GRFILTER_FILTERERROR;
             else
-                eLinkType = GfxLinkType::NativeJpg;
+            {
+                Bitmap& rBitmap = const_cast<Bitmap&>(rGraphic.GetBitmapExRef().GetBitmapRef());
+                Bitmap::ScopedWriteAccess pWriteAccess(rBitmap);
+                rIStream.Seek(nPosition);
+                if( !ImportJPEG( rIStream, rGraphic, nImportFlags | GraphicFilterImportFlags::UseExistingBitmap, &pWriteAccess ) )
+                    nStatus = GRFILTER_FILTERERROR;
+                else
+                    eLinkType = GfxLinkType::NativeJpg;
+            }
         }
         else if( aFilterName.equalsIgnoreAsciiCase( IMP_SVG ) )
         {
diff --git a/vcl/source/filter/jpeg/JpegReader.cxx b/vcl/source/filter/jpeg/JpegReader.cxx
index 9f8510a4f4b1..9f7185f23f36 100644
--- a/vcl/source/filter/jpeg/JpegReader.cxx
+++ b/vcl/source/filter/jpeg/JpegReader.cxx
@@ -169,14 +169,19 @@ void jpeg_svstream_src (j_decompress_ptr cinfo, void* input)
     source->pub.next_input_byte = nullptr; /* until buffer loaded */
 }
 
-JPEGReader::JPEGReader( SvStream& rStream, bool bSetLogSize ) :
+JPEGReader::JPEGReader( SvStream& rStream, GraphicFilterImportFlags nImportFlags ) :
     mrStream         ( rStream ),
     mnLastPos        ( rStream.Tell() ),
     mnLastLines      ( 0 ),
-    mbSetLogSize     ( bSetLogSize )
+    mbSetLogSize     ( nImportFlags & GraphicFilterImportFlags::SetLogsizeForJpeg )
 {
     maUpperName = "SVIJPEG";
-    mnFormerPos = mnLastPos;
+
+    if (!(nImportFlags & GraphicFilterImportFlags::UseExistingBitmap))
+    {
+        mpBitmap.reset(new Bitmap());
+        mpIncompleteAlpha.reset(new Bitmap());
+    }
 }
 
 JPEGReader::~JPEGReader()
@@ -194,7 +199,7 @@ bool JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
     Size aSize(rParam.nWidth, rParam.nHeight);
     bool bGray = rParam.bGray;
 
-    maBitmap = Bitmap();
+    mpBitmap.reset(new Bitmap());
 
     sal_uInt64 nSize = aSize.Width() * aSize.Height();
 
@@ -211,11 +216,11 @@ bool JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
             aGrayPal[ n ] = BitmapColor( cGray, cGray, cGray );
         }
 
-        maBitmap = Bitmap(aSize, 8, &aGrayPal);
+        mpBitmap.reset(new Bitmap(aSize, 8, &aGrayPal));
     }
     else
     {
-        maBitmap = Bitmap(aSize, 24);
+        mpBitmap.reset(new Bitmap(aSize, 24));
     }
 
     if (mbSetLogSize)
@@ -230,8 +235,8 @@ bool JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
             MapMode     aMapMode( nUnit == 1 ? MapUnit::MapInch : MapUnit::MapCM, aEmptyPoint, aFractX, aFractY );
             Size        aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MapUnit::Map100thMM );
 
-            maBitmap.SetPrefSize(aPrefSize);
-            maBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+            mpBitmap->SetPrefSize(aPrefSize);
+            mpBitmap->SetPrefMapMode(MapMode(MapUnit::Map100thMM));
         }
     }
 
@@ -241,12 +246,12 @@ bool JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
 Graphic JPEGReader::CreateIntermediateGraphic(long nLines)
 {
     Graphic aGraphic;
-    const Size aSizePixel(maBitmap.GetSizePixel());
+    const Size aSizePixel(mpBitmap->GetSizePixel());
 
     if (!mnLastLines)
     {
-        maIncompleteAlpha = Bitmap(aSizePixel, 1);
-        maIncompleteAlpha.Erase(Color(COL_WHITE));
+        mpIncompleteAlpha.reset(new Bitmap(aSizePixel, 1));
+        mpIncompleteAlpha->Erase(Color(COL_WHITE));
     }
 
     if (nLines && (nLines < aSizePixel.Height()))
@@ -256,21 +261,21 @@ Graphic JPEGReader::CreateIntermediateGraphic(long nLines)
         if (nNewLines > 0)
         {
             {
-                Bitmap::ScopedWriteAccess pAccess(maIncompleteAlpha);
+                Bitmap::ScopedWriteAccess pAccess(*mpIncompleteAlpha);
                 pAccess->SetFillColor(Color(COL_BLACK));
                 pAccess->FillRect(Rectangle(Point(0, mnLastLines), Size(pAccess->Width(), nNewLines)));
             }
 
-            aGraphic = BitmapEx(maBitmap, maIncompleteAlpha);
+            aGraphic = BitmapEx(*mpBitmap, *mpIncompleteAlpha);
         }
         else
         {
-            aGraphic = maBitmap;
+            aGraphic = *mpBitmap;
         }
     }
     else
     {
-        aGraphic = maBitmap;
+        aGraphic = *mpBitmap;
     }
 
     mnLastLines = nLines;
@@ -278,10 +283,9 @@ Graphic JPEGReader::CreateIntermediateGraphic(long nLines)
     return aGraphic;
 }
 
-ReadState JPEGReader::Read( Graphic& rGraphic )
+ReadState JPEGReader::Read( Graphic& rGraphic, GraphicFilterImportFlags nImportFlags, Bitmap::ScopedWriteAccess* ppAccess )
 {
     long        nEndPosition;
-    long        nLines;
     ReadState   eReadState;
     bool        bRet = false;
     sal_uInt8   cDummy;
@@ -307,9 +311,11 @@ ReadState JPEGReader::Read( Graphic& rGraphic )
     mrStream.Seek( mnLastPos );
 
     // read the (partial) image
-    ReadJPEG( this, &mrStream, &nLines, GetPreviewSize() );
+    long nLines;
+    ReadJPEG( this, &mrStream, &nLines, GetPreviewSize(), nImportFlags, ppAccess );
 
-    if (!maBitmap.IsEmpty())
+    auto bUseExistingBitmap = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::UseExistingBitmap);
+    if (bUseExistingBitmap || !mpBitmap->IsEmpty())
     {
         if( mrStream.GetError() == ERRCODE_IO_PENDING )
         {
@@ -317,7 +323,8 @@ ReadState JPEGReader::Read( Graphic& rGraphic )
         }
         else
         {
-            rGraphic = maBitmap;
+            if (!bUseExistingBitmap)
+                rGraphic = *mpBitmap;
         }
 
         bRet = true;
diff --git a/vcl/source/filter/jpeg/JpegReader.hxx b/vcl/source/filter/jpeg/JpegReader.hxx
index bb020f449f19..e45a4421867c 100644
--- a/vcl/source/filter/jpeg/JpegReader.hxx
+++ b/vcl/source/filter/jpeg/JpegReader.hxx
@@ -21,10 +21,13 @@
 #define INCLUDED_VCL_SOURCE_FILTER_JPEG_JPEGREADER_HXX
 
 #include <vcl/graph.hxx>
+#include <vcl/bitmap.hxx>
 #include <vcl/fltcall.hxx>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/task/XStatusIndicator.hpp>
 
+enum class GraphicFilterImportFlags;
+
 enum ReadState
 {
     JPEGREAD_OK,
@@ -46,8 +49,8 @@ struct JPEGCreateBitmapParam
 class JPEGReader : public GraphicReader
 {
     SvStream&           mrStream;
-    Bitmap              maBitmap;
-    Bitmap              maIncompleteAlpha;
+    std::unique_ptr<Bitmap> mpBitmap;
+    std::unique_ptr<Bitmap> mpIncompleteAlpha;
 
     long                mnLastPos;
     long                mnFormerPos;
@@ -57,14 +60,14 @@ class JPEGReader : public GraphicReader
     Graphic CreateIntermediateGraphic(long nLines);
 
 public:
-            JPEGReader( SvStream& rStream, bool bSetLogSize );
+            JPEGReader( SvStream& rStream, GraphicFilterImportFlags nImportFlags );
     virtual ~JPEGReader() override;
 
-    ReadState Read(Graphic& rGraphic);
+    ReadState Read(Graphic& rGraphic, GraphicFilterImportFlags nImportFlags, Bitmap::ScopedWriteAccess* ppAccess);
 
     bool CreateBitmap(JPEGCreateBitmapParam& param);
 
-    Bitmap& GetBitmap() { return maBitmap; }
+    Bitmap& GetBitmap() { return *mpBitmap; }
 };
 
 #endif // INCLUDED_VCL_SOURCE_FILTER_JPEG_JPEGREADER_HXX
diff --git a/vcl/source/filter/jpeg/jpeg.cxx b/vcl/source/filter/jpeg/jpeg.cxx
index f1cb2eb2ed65..5b067153dc30 100644
--- a/vcl/source/filter/jpeg/jpeg.cxx
+++ b/vcl/source/filter/jpeg/jpeg.cxx
@@ -25,7 +25,7 @@
 #include <vcl/FilterConfigItem.hxx>
 #include <vcl/graphicfilter.hxx>
 
-VCL_DLLPUBLIC bool ImportJPEG( SvStream& rInputStream, Graphic& rGraphic, GraphicFilterImportFlags nImportFlags )
+VCL_DLLPUBLIC bool ImportJPEG( SvStream& rInputStream, Graphic& rGraphic, GraphicFilterImportFlags nImportFlags, Bitmap::ScopedWriteAccess* ppAccess )
 {
     bool        bReturn = true;
 
@@ -34,7 +34,7 @@ VCL_DLLPUBLIC bool ImportJPEG( SvStream& rInputStream, Graphic& rGraphic, Graphi
     JPEGReader* pJPEGReader = dynamic_cast<JPEGReader*>( pContext.get() );
     if (!pJPEGReader)
     {
-        pContext = std::make_shared<JPEGReader>( rInputStream, bool( nImportFlags & GraphicFilterImportFlags::SetLogsizeForJpeg ) );
+        pContext = std::make_shared<JPEGReader>( rInputStream, nImportFlags );
         pJPEGReader = static_cast<JPEGReader*>( pContext.get() );
     }
 
@@ -47,7 +47,7 @@ VCL_DLLPUBLIC bool ImportJPEG( SvStream& rInputStream, Graphic& rGraphic, Graphi
         pJPEGReader->DisablePreviewMode();
     }
 
-    ReadState eReadState = pJPEGReader->Read( rGraphic );
+    ReadState eReadState = pJPEGReader->Read( rGraphic, nImportFlags, ppAccess );
 
     if( eReadState == JPEGREAD_ERROR )
     {
diff --git a/vcl/source/filter/jpeg/jpeg.h b/vcl/source/filter/jpeg/jpeg.h
index 08caa474226c..4d542c5c7110 100644
--- a/vcl/source/filter/jpeg/jpeg.h
+++ b/vcl/source/filter/jpeg/jpeg.h
@@ -25,6 +25,8 @@
 #include <com/sun/star/uno/Reference.hxx>
 #include <sal/types.h>
 #include <basegfx/vector/b2dsize.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/graphicfilter.hxx>
 
 #include <jpeglib.h>
 
@@ -45,7 +47,8 @@ bool    WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream,
                    css::uno::Reference<css::task::XStatusIndicator> const & status);
 
 void    ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
-                  Size const & previewSize );
+                  Size const & previewSize, GraphicFilterImportFlags nImportFlags,
+                  Bitmap::ScopedWriteAccess* ppAccess );
 
 long    Transform( void* pInputStream, void* pOutputStream, long nAngle );
 
diff --git a/vcl/source/filter/jpeg/jpeg.hxx b/vcl/source/filter/jpeg/jpeg.hxx
index f8f900ace03d..776e7d60042f 100644
--- a/vcl/source/filter/jpeg/jpeg.hxx
+++ b/vcl/source/filter/jpeg/jpeg.hxx
@@ -23,11 +23,12 @@
 #include <vcl/graph.hxx>
 #include <vcl/graphicfilter.hxx>
 #include <vcl/fltcall.hxx>
+#include <vcl/bitmap.hxx>
 #include <com/sun/star/uno/Sequence.h>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/task/XStatusIndicator.hpp>
 
-VCL_DLLPUBLIC bool ImportJPEG( SvStream& rInputStream, Graphic& rGraphic, GraphicFilterImportFlags nImportFlags );
+VCL_DLLPUBLIC bool ImportJPEG( SvStream& rInputStream, Graphic& rGraphic, GraphicFilterImportFlags nImportFlags, Bitmap::ScopedWriteAccess* ppAccess );
 
 bool ExportJPEG(SvStream& rOutputStream,
                     const Graphic& rGraphic,
diff --git a/vcl/source/filter/jpeg/jpegc.cxx b/vcl/source/filter/jpeg/jpegc.cxx
index 3353fe9c247a..06c36a821f5c 100644
--- a/vcl/source/filter/jpeg/jpegc.cxx
+++ b/vcl/source/filter/jpeg/jpegc.cxx
@@ -37,6 +37,7 @@ extern "C" {
 #include <JpegWriter.hxx>
 #include <memory>
 #include <vcl/bitmapaccess.hxx>
+#include <vcl/graphicfilter.hxx>
 
 #ifdef _MSC_VER
 #pragma warning(push, 1) /* disable to __declspec(align()) aligned warning */
@@ -67,7 +68,8 @@ extern "C" void outputMessage (j_common_ptr cinfo)
 }
 
 void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
-               Size const & previewSize )
+               Size const & previewSize, GraphicFilterImportFlags nImportFlags,
+               Bitmap::ScopedWriteAccess* ppAccess )
 {
     jpeg_decompress_struct cinfo;
     ErrorManagerStruct jerr;
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
index e1dbdd9ad3cb..cc47fb748ae4 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -249,6 +249,11 @@ bool BitmapEx::IsAlpha() const
     return( IsTransparent() && bAlpha );
 }
 
+const Bitmap& BitmapEx::GetBitmapRef() const
+{
+    return aBitmap;
+}
+
 Bitmap BitmapEx::GetBitmap( const Color* pTransReplaceColor ) const
 {
     Bitmap aRetBmp( aBitmap );
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index 74aaacc6c421..d22a29779d8b 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -354,6 +354,11 @@ const GDIMetaFile& Graphic::GetGDIMetaFile() const
     return mxImpGraphic->ImplGetGDIMetaFile();
 }
 
+const BitmapEx& Graphic::GetBitmapExRef() const
+{
+    return mxImpGraphic->ImplGetBitmapExRef();
+}
+
 uno::Reference< graphic::XGraphic > Graphic::GetXGraphic() const
 {
     uno::Reference< graphic::XGraphic > xRet;
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index e0215eb9ab26..64b5bab9ac75 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -648,6 +648,11 @@ Animation ImpGraphic::ImplGetAnimation() const
     return aAnimation;
 }
 
+const BitmapEx& ImpGraphic::ImplGetBitmapExRef() const
+{
+    return maEx;
+}
+
 const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const
 {
     ensureAvailable();
diff --git a/vcl/workben/fftester.cxx b/vcl/workben/fftester.cxx
index 45d10f928e86..7ea02538cd3d 100644
--- a/vcl/workben/fftester.cxx
+++ b/vcl/workben/fftester.cxx
@@ -114,7 +114,7 @@ try_again:
             {
                 Graphic aGraphic;
                 SvFileStream aFileStream(out, StreamMode::READ);
-                ret = (int) ImportJPEG(aFileStream, aGraphic, GraphicFilterImportFlags::NONE);
+                ret = (int) ImportJPEG(aFileStream, aGraphic, GraphicFilterImportFlags::NONE, nullptr);
                 BitmapEx aTarget = aGraphic.GetBitmapEx();
                 aTarget.Convert(BmpConversion::N24Bit);
             }
commit 8c466f6f08c1c6bcf84a6b611d5afd2ef7cdc98b
Author: Noel Grandin <noel.grandin at collabora.co.uk>
Date:   Thu Sep 28 11:28:15 2017 +0200

    convert GfxLink::IsEqual to operator==
    
    exactly one use site
    
    Change-Id: Id0a75d46c459be213e81b47aa6c1194c87aec848
    Reviewed-on: https://gerrit.libreoffice.org/42891
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
    Tested-by: Noel Grandin <noel.grandin at collabora.co.uk>
    (cherry picked from commit ce301dadcbbf8d0f0a71c7eaebca9bfad2e08801)

diff --git a/drawinglayer/source/primitive2d/epsprimitive2d.cxx b/drawinglayer/source/primitive2d/epsprimitive2d.cxx
index 197a0b1d9032..533cdb30ce52 100644
--- a/drawinglayer/source/primitive2d/epsprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/epsprimitive2d.cxx
@@ -60,7 +60,7 @@ namespace drawinglayer
                 const EpsPrimitive2D& rCompare = static_cast<const EpsPrimitive2D&>(rPrimitive);
 
                 return (getEpsTransform() == rCompare.getEpsTransform()
-                    && getGfxLink().IsEqual(rCompare.getGfxLink())
+                    && getGfxLink() == rCompare.getGfxLink()
                     && getMetaFile() == rCompare.getMetaFile());
             }
 
diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx
index 3632b66d23f3..d8eef9e3ce3a 100644
--- a/include/vcl/gfxlink.hxx
+++ b/include/vcl/gfxlink.hxx
@@ -83,7 +83,7 @@ public:
                         // pBuff = The Graphic data. This class takes ownership of this
                         GfxLink( std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nBufSize, GfxLinkType nType );
 
-    bool                IsEqual( const GfxLink& ) const;
+    bool                operator==( const GfxLink& ) const;
 
     GfxLinkType         GetType() const { return meType;}
 
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
index 4fdd0e1398e9..8f7c3708f28a 100644
--- a/vcl/source/gdi/gfxlink.cxx
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -45,7 +45,7 @@ GfxLink::GfxLink( std::unique_ptr<sal_uInt8[]> pBuf, sal_uInt32 nSize, GfxLinkTy
     mpSwapInData = std::shared_ptr<sal_uInt8>(pBuf.release(), pBuf.get_deleter());  // std::move(pBuf) does not compile on Jenkins MacOSX (24 May 2016)
 }
 
-bool GfxLink::IsEqual( const GfxLink& rGfxLink ) const
+bool GfxLink::operator==( const GfxLink& rGfxLink ) const
 {
     bool bIsEqual = false;
 
commit d56c7c9a22096005ebb9a333df6311c8a33650bc
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Apr 4 17:51:26 2018 +0900

    vcl: Add a internal (memory) manager for Graphic objects
    
    This adds vcl::graphic::Manager which is a manager singleton that
    tracks all the creation fo graphic objects and swaps them out on
    a time and allocation basis.
    
    Time based - every number of seconds it looks for Graphics that
    weren't used for a time.
    
    Allocation based - when creating a new Graphic and the total of
    Graphic uses more than the total amount of memory for Graphics
    defined in configuration, it tries to release the Graphics that
    weren't used for a time.
    
    Reviewed-on: https://gerrit.libreoffice.org/52396
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit a2b53fece14f745853bcfe1a300c3dceb580e148)
    
    Change-Id: I5dbf74db4a6455d32c4abcbad7be21c7f0534642


... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list