include/vcl/pdfread.hxx            |    5 +
 vcl/source/filter/ipdf/pdfread.cxx |  121 +++++++++++++++++++------------------
 vcl/source/gdi/impgraph.cxx        |   40 +++++++-----
 3 files changed, 93 insertions(+), 73 deletions(-)

New commits:
commit 6a96ea6378986ad7a8951dde583ae590edae1a65
Author:     Jan Holesovsky <ke...@collabora.com>
AuthorDate: Fri Jun 22 00:44:44 2018 +0200
Commit:     Jan Holesovsky <ke...@collabora.com>
CommitDate: Tue Mar 26 13:56:08 2019 +0100

    pdfium: Keep the PDF data in memory, so that we can really share them.
    
    Otherwise the swap out / swap in creates new copy of the underlying PDF
    stream.
    
    Change-Id: I88a16a69143783a998201e183bea1a9553e337bd
    Reviewed-on: https://gerrit.libreoffice.org/56266
    Reviewed-by: Ashod Nakashian <ashnak...@gmail.com>
    Tested-by: Ashod Nakashian <ashnak...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/69626
    Reviewed-by: Jan Holesovsky <ke...@collabora.com>
    Tested-by: Jan Holesovsky <ke...@collabora.com>

diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx
index 1a1ff0d680cb..c491f50ef34b 100644
--- a/include/vcl/pdfread.hxx
+++ b/include/vcl/pdfread.hxx
@@ -16,6 +16,11 @@
 
 namespace vcl
 {
+/// Fills the rBitmaps vector with rendered pages.
+VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, 
std::vector<Bitmap>& rBitmaps,
+                                      const size_t nFirstPage = 0, int nPages 
= 1,
+                                      const double fResolutionDPI = 96.);
+
 /// 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>& rPdfData,
diff --git a/vcl/source/filter/ipdf/pdfread.cxx 
b/vcl/source/filter/ipdf/pdfread.cxx
index ab70a0451d9d..16cb902e2476 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -63,68 +63,12 @@ size_t generatePreview(SvStream& rStream, 
std::vector<Bitmap>& rBitmaps,
                        const size_t nFirstPage = 0, int nPages = 1,
                        const double fResolutionDPI = 96.)
 {
-    FPDF_LIBRARY_CONFIG aConfig;
-    aConfig.version = 2;
-    aConfig.m_pUserFontPaths = nullptr;
-    aConfig.m_pIsolate = nullptr;
-    aConfig.m_v8EmbedderSlot = 0;
-    FPDF_InitLibraryWithConfig(&aConfig);
-
     // Read input into a buffer.
     SvMemoryStream aInBuffer;
     rStream.Seek(nPos);
     aInBuffer.WriteStream(rStream, nSize);
 
-    // Load the buffer using pdfium.
-    FPDF_DOCUMENT pPdfDocument = FPDF_LoadMemDocument(aInBuffer.GetData(), 
aInBuffer.GetSize(), /*password=*/nullptr);
-    if (!pPdfDocument)
-        return 0;
-
-    const int nPageCount = FPDF_GetPageCount(pPdfDocument);
-    if (nPages <= 0)
-        nPages = nPageCount;
-    const size_t nLastPage = std::min<int>(nPageCount, nFirstPage + nPages) - 
1;
-    for (size_t nPageIndex = nFirstPage; nPageIndex <= nLastPage; ++nPageIndex)
-    {
-        // Render next page.
-        FPDF_PAGE pPdfPage = FPDF_LoadPage(pPdfDocument, nPageIndex);
-        if (!pPdfPage)
-            break;
-
-        // Returned unit is points, convert that to pixel.
-        const size_t nPageWidth = pointToPixel(FPDF_GetPageWidth(pPdfPage), 
fResolutionDPI);
-        const size_t nPageHeight = pointToPixel(FPDF_GetPageHeight(pPdfPage), 
fResolutionDPI);
-        FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, 
/*alpha=*/1);
-        if (!pPdfBitmap)
-            break;
-
-        const FPDF_DWORD nColor = FPDFPage_HasTransparency(pPdfPage) ? 
0x00000000 : 0xFFFFFFFF;
-        FPDFBitmap_FillRect(pPdfBitmap, 0, 0, nPageWidth, nPageHeight, nColor);
-        FPDF_RenderPageBitmap(pPdfBitmap, pPdfPage, /*start_x=*/0, 
/*start_y=*/0, nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0);
-
-        // Save the buffer as a bitmap.
-        Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24);
-        {
-            Bitmap::ScopedWriteAccess pWriteAccess(aBitmap);
-            const auto pPdfBuffer = 
static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap));
-            const int nStride = FPDFBitmap_GetStride(pPdfBitmap);
-            for (size_t nRow = 0; nRow < nPageHeight; ++nRow)
-            {
-                ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow);
-                // pdfium byte order is BGRA.
-                pWriteAccess->CopyScanline(nRow, pPdfLine, 
ScanlineFormat::N32BitTcBgra, nStride);
-            }
-        }
-
-        rBitmaps.emplace_back(std::move(aBitmap));
-        FPDFBitmap_Destroy(pPdfBitmap);
-        FPDF_ClosePage(pPdfPage);
-    }
-
-    FPDF_CloseDocument(pPdfDocument);
-    FPDF_DestroyLibrary();
-
-    return rBitmaps.size();
+    return vcl::RenderPDFBitmaps(aInBuffer.GetData(), aInBuffer.GetSize(), 
rBitmaps, nFirstPage, nPages, fResolutionDPI);
 }
 
 /// Decide if PDF data is old enough to be compatible.
@@ -211,6 +155,69 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& 
rOutStream,
 namespace vcl
 {
 
+size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& 
rBitmaps,
+                        const size_t nFirstPage, int nPages,
+                        const double fResolutionDPI)
+{
+    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(pBuffer, nSize, 
/*password=*/nullptr);
+    if (!pPdfDocument)
+        return 0;
+
+    const int nPageCount = FPDF_GetPageCount(pPdfDocument);
+    if (nPages <= 0)
+        nPages = nPageCount;
+    const size_t nLastPage = std::min<int>(nPageCount, nFirstPage + nPages) - 
1;
+    for (size_t nPageIndex = nFirstPage; nPageIndex <= nLastPage; ++nPageIndex)
+    {
+        // Render next page.
+        FPDF_PAGE pPdfPage = FPDF_LoadPage(pPdfDocument, nPageIndex);
+        if (!pPdfPage)
+            break;
+
+        // Returned unit is points, convert that to pixel.
+        const size_t nPageWidth = pointToPixel(FPDF_GetPageWidth(pPdfPage), 
fResolutionDPI);
+        const size_t nPageHeight = pointToPixel(FPDF_GetPageHeight(pPdfPage), 
fResolutionDPI);
+        FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, 
/*alpha=*/1);
+        if (!pPdfBitmap)
+            break;
+
+        const FPDF_DWORD nColor = FPDFPage_HasTransparency(pPdfPage) ? 
0x00000000 : 0xFFFFFFFF;
+        FPDFBitmap_FillRect(pPdfBitmap, 0, 0, nPageWidth, nPageHeight, nColor);
+        FPDF_RenderPageBitmap(pPdfBitmap, pPdfPage, /*start_x=*/0, 
/*start_y=*/0, nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0);
+
+        // Save the buffer as a bitmap.
+        Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24);
+        {
+            Bitmap::ScopedWriteAccess pWriteAccess(aBitmap);
+            const auto pPdfBuffer = 
static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap));
+            const int nStride = FPDFBitmap_GetStride(pPdfBitmap);
+            for (size_t nRow = 0; nRow < nPageHeight; ++nRow)
+            {
+                ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow);
+                // pdfium byte order is BGRA.
+                pWriteAccess->CopyScanline(nRow, pPdfLine, 
ScanlineFormat::N32BitTcBgra, nStride);
+            }
+        }
+
+        rBitmaps.emplace_back(std::move(aBitmap));
+        FPDFBitmap_Destroy(pPdfBitmap);
+        FPDF_ClosePage(pPdfPage);
+    }
+
+    FPDF_CloseDocument(pPdfDocument);
+    FPDF_DestroyLibrary();
+
+    return rBitmaps.size();
+}
+
 bool ImportPDF(SvStream& rStream, Bitmap& rBitmap,
                size_t nPageIndex,
                css::uno::Sequence<sal_Int8>& rPdfData,
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 6e837c979e78..87c2c233a732 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -37,6 +37,7 @@
 #include <impgraph.hxx>
 #include <com/sun/star/ucb/CommandAbortedException.hpp>
 #include <vcl/dibtools.hxx>
+#include <map>
 #include <memory>
 #include <o3tl/make_unique.hxx>
 #include <vcl/gdimetafiletools.hxx>
@@ -1475,6 +1476,7 @@ bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const
     return bResult;
 }
 
+static std::map<BitmapChecksum, std::shared_ptr<css::uno::Sequence<sal_Int8>>> 
sPdfDataCache;
 
 void ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic )
 {
@@ -1623,23 +1625,25 @@ void ReadImpGraphic( SvStream& rIStm, ImpGraphic& 
rImpGraphic )
             else if (nMagic == nPdfMagic)
             {
                 // Stream in PDF data.
-                sal_uInt32 nPdfDataLength = 0;
-                rIStm.ReadUInt32(nPdfDataLength);
+                BitmapChecksum nPdfId = 0;
+                rIStm.ReadUInt64(nPdfId);
+
+                rImpGraphic.mnPageNumber = 0;
+                rIStm.ReadInt32(rImpGraphic.mnPageNumber);
+
+                auto it = sPdfDataCache.find(nPdfId);
+                assert(it != sPdfDataCache.end());
+
+                rImpGraphic.mpPdfData = it->second;
+
                 Bitmap aBitmap;
+                rImpGraphic.maEx = aBitmap;
 
-                if (nPdfDataLength && !rIStm.GetError())
-                {
-                    if (!rImpGraphic.mpPdfData)
-                        rImpGraphic.mpPdfData.reset(new 
uno::Sequence<sal_Int8>());
+                std::vector<Bitmap> aBitmaps;
+                if 
(vcl::RenderPDFBitmaps(rImpGraphic.mpPdfData->getConstArray(), 
rImpGraphic.mpPdfData->getLength(), aBitmaps, rImpGraphic.mnPageNumber, 1) == 1)
+                    rImpGraphic.maEx = aBitmaps[0];
 
-                    if (vcl::ImportPDF(rIStm, aBitmap, 
rImpGraphic.mnPageNumber,
-                                       *rImpGraphic.mpPdfData,
-                                       rIStm.Tell(), nPdfDataLength))
-                    {
-                        rImpGraphic.maEx = aBitmap;
-                        rImpGraphic.meType = GraphicType::Bitmap;
-                    }
-                }
+                rImpGraphic.meType = GraphicType::Bitmap;
             }
             else
             {
@@ -1730,10 +1734,14 @@ void WriteImpGraphic(SvStream& rOStm, const ImpGraphic& 
rImpGraphic)
                 }
                 else if (rImpGraphic.hasPdfData())
                 {
+                    BitmapChecksum nPdfId = vcl_get_checksum(0, 
rImpGraphic.mpPdfData->getConstArray(), rImpGraphic.mpPdfData->getLength());
+                    if (sPdfDataCache.find(nPdfId) == sPdfDataCache.end())
+                        sPdfDataCache.emplace(nPdfId, rImpGraphic.mpPdfData);
+
                     // Stream out PDF data.
                     rOStm.WriteUInt32(nPdfMagic);
-                    rOStm.WriteUInt32(rImpGraphic.mpPdfData->getLength());
-                    rOStm.WriteBytes(rImpGraphic.mpPdfData->getConstArray(), 
rImpGraphic.mpPdfData->getLength());
+                    rOStm.WriteUInt64(nPdfId);
+                    rOStm.WriteInt32(rImpGraphic.mnPageNumber);
                 }
                 else if( rImpGraphic.ImplIsAnimated())
                 {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to