[Libreoffice-commits] core.git: include/vcl vcl/source

Jan Holesovsky (via logerrit) logerrit at kemper.freedesktop.org
Sun Aug 25 11:31:49 UTC 2019


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

New commits:
commit e4cec56a699b75102c39f4f80879a8080fc5ecc1
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Fri Jun 22 00:44:44 2018 +0200
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Sun Aug 25 13:30:37 2019 +0200

    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 <ashnakash at gmail.com>
    Tested-by: Ashod Nakashian <ashnakash at gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/69626
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>
    Tested-by: Jan Holesovsky <kendy at collabora.com>
    (cherry picked from commit 826208d2da6c92e94b38ef447e47550285742755)
    Reviewed-on: https://gerrit.libreoffice.org/77687
    Tested-by: Jenkins

diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx
index 346c39a3a897..1de9cfc9b259 100644
--- a/include/vcl/pdfread.hxx
+++ b/include/vcl/pdfread.hxx
@@ -31,6 +31,11 @@ class Graphic;
 
 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 edd354f19e5b..63162c6e2ad2 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -41,80 +41,23 @@ int CompatibleWriterCallback(FPDF_FILEWRITE* pFileWrite, const void* pData, unsi
 }
 
 /// Convert to inch, then assume 96 DPI.
-double pointToPixel(const double fPoint, const double fResolutionDPI)
+inline double pointToPixel(const double fPoint, const double fResolutionDPI)
 {
     return fPoint * fResolutionDPI / 72.;
 }
 
 /// Does PDF to bitmap conversion using pdfium.
 size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, sal_uInt64 nPos,
-                       sal_uInt64 nSize, const size_t nFirstPage, int nPages,
+                       sal_uInt64 nSize, 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);
-        {
-            BitmapScopedWriteAccess 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.
@@ -205,6 +148,69 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 n
 
 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);
+        {
+            BitmapScopedWriteAccess 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, sal_uInt64 nPos, sal_uInt64 nSize,
                const double fResolutionDPI)
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 69e578d0e235..8b283081b966 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -41,6 +41,7 @@
 #include <com/sun/star/ucb/ContentCreationException.hpp>
 #include <com/sun/star/graphic/XPrimitive2D.hpp>
 #include <vcl/dibtools.hxx>
+#include <map>
 #include <memory>
 #include <vcl/gdimetafiletools.hxx>
 
@@ -1731,6 +1732,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 )
 {
@@ -1879,23 +1881,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
             {
@@ -1988,10 +1992,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())
                 {


More information about the Libreoffice-commits mailing list