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

Jan-Marek Glogowski glogow at fbihome.de
Mon Nov 6 14:49:49 UTC 2017


 include/tools/stream.hxx            |    1 
 tools/source/stream/stream.cxx      |   21 +++++++++++
 vcl/inc/pdfread.hxx                 |    4 ++
 vcl/source/filter/graphicfilter.cxx |    2 -
 vcl/source/filter/ipdf/pdfread.cxx  |   66 ++++++++++++++++++++++++------------
 vcl/source/gdi/impgraph.cxx         |   13 ++++---
 6 files changed, 79 insertions(+), 28 deletions(-)

New commits:
commit 3a88795c1211c62277dc646e61c2ba8306febe37
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Thu Oct 26 16:05:54 2017 +0200

    tdf#108748 generate PDF preview on SwapIn
    
    When including a PDF as an image, it's represented internally as
    a Bitmap with additional PDF data. On SwapIn, LibreOffice just
    imported the PDF data missing the PDF preview. The Graphic also
    gad the wrong image type, which results in a busy loop on master,
    with a strange / unhelpful STR_COMCORE_READERROR generated by
    SwNoTextFrame::PaintPicture.
    
    This is a workaround to generate the Bitmap on SwapIn, which
    will really slow down LibreOffice when importing many PDFs.
    
    I guess the job of generating the PDF previews should probably
    be deferred to a thread or a low priority Scheduler task, just
    like the general image loading is handled.
    
    Change-Id: I8084e4533995ecddc5b03ef19cb0c6a2dbf60ebd
    Reviewed-on: https://gerrit.libreoffice.org/43906
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>

diff --git a/include/tools/stream.hxx b/include/tools/stream.hxx
index 00aa872f53e3..64823f48d078 100644
--- a/include/tools/stream.hxx
+++ b/include/tools/stream.hxx
@@ -252,6 +252,7 @@ public:
     SvStream&       WriteOString(const OString& rStr)
                         { return WriteCharPtr(rStr.getStr()); }
     SvStream&       WriteStream( SvStream& rStream );
+    sal_uInt64      WriteStream( SvStream& rStream, sal_uInt64 nSize );
 
     SvStream&       WriteBool( bool b )
                         { return WriteUChar(static_cast<unsigned char>(b)); }
diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx
index 4f95afd2c1e8..4c363dc67484 100644
--- a/tools/source/stream/stream.cxx
+++ b/tools/source/stream/stream.cxx
@@ -1179,6 +1179,27 @@ SvStream& SvStream::WriteStream( SvStream& rStream )
     return *this;
 }
 
+sal_uInt64 SvStream::WriteStream( SvStream& rStream, sal_uInt64 nSize )
+{
+    const sal_uInt32 cBufLen = 0x8000;
+    std::unique_ptr<char[]> pBuf( new char[ cBufLen ] );
+    sal_uInt32 nCurBufLen = cBufLen;
+    sal_uInt32 nCount;
+    sal_uInt64 nWriteSize = nSize;
+
+    do {
+        if ( nSize >= nCurBufLen )
+            nWriteSize -= nCurBufLen;
+        else
+            nCurBufLen = nWriteSize;
+        nCount = rStream.ReadBytes( pBuf.get(), nCurBufLen );
+        WriteBytes( pBuf.get(), nCount );
+    }
+    while( nWriteSize && nCount == nCurBufLen );
+
+    return nSize - nWriteSize;
+}
+
 OUString SvStream::ReadUniOrByteString( rtl_TextEncoding eSrcCharSet )
 {
     // read UTF-16 string directly from stream ?
diff --git a/vcl/source/filter/ipdf/pdfread.hxx b/vcl/inc/pdfread.hxx
similarity index 73%
rename from vcl/source/filter/ipdf/pdfread.hxx
rename to vcl/inc/pdfread.hxx
index 2cb3abd7bc01..e873c49a1cdd 100644
--- a/vcl/source/filter/ipdf/pdfread.hxx
+++ b/vcl/inc/pdfread.hxx
@@ -17,6 +17,10 @@ namespace vcl
 {
 
 /// Imports a PDF stream into rGraphic as a GDIMetaFile.
+VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap &rBitmap,
+                             css::uno::Sequence<sal_Int8> &rPdfFata,
+                             sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN,
+                             sal_uInt64 nSize = STREAM_SEEK_TO_END);
 VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic);
 
 }
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 776ef710eee7..062f5ee3701d 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -44,7 +44,7 @@
 #include <vcl/wmf.hxx>
 #include <vcl/settings.hxx>
 #include "igif/gifread.hxx"
-#include "ipdf/pdfread.hxx"
+#include <pdfread.hxx>
 #include "jpeg/jpeg.hxx"
 #include "ixbm/xbmread.hxx"
 #include "ixpm/xpmread.hxx"
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index 254e2adf1cd8..59a7b1f80469 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -7,7 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include "pdfread.hxx"
+#include <pdfread.hxx>
 
 #include <config_features.h>
 
@@ -56,7 +56,8 @@ double pointToPixel(double fPoint)
 }
 
 /// Does PDF to bitmap conversion using pdfium.
-bool generatePreview(SvStream& rStream, Graphic& rGraphic)
+bool generatePreview(SvStream& rStream, Bitmap& rBitmap,
+                     sal_uInt64 nPos, sal_uInt64 nSize)
 {
     FPDF_LIBRARY_CONFIG aConfig;
     aConfig.version = 2;
@@ -67,7 +68,8 @@ bool generatePreview(SvStream& rStream, Graphic& rGraphic)
 
     // Read input into a buffer.
     SvMemoryStream aInBuffer;
-    aInBuffer.WriteStream(rStream);
+    rStream.Seek(nPos);
+    aInBuffer.WriteStream(rStream, nSize);
 
     // Load the buffer using pdfium.
     FPDF_DOCUMENT pPdfDocument = FPDF_LoadMemDocument(aInBuffer.GetData(), aInBuffer.GetSize(), /*password=*/nullptr);
@@ -103,7 +105,7 @@ bool generatePreview(SvStream& rStream, Graphic& rGraphic)
             pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride);
         }
     }
-    rGraphic = aBitmap;
+    rBitmap = aBitmap;
 
     FPDFBitmap_Destroy(pPdfBitmap);
     FPDF_ClosePage(pPdfPage);
@@ -114,11 +116,14 @@ bool generatePreview(SvStream& rStream, Graphic& rGraphic)
 }
 
 /// Decide if PDF data is old enough to be compatible.
-bool isCompatible(SvStream& rInStream)
+bool isCompatible(SvStream& rInStream, sal_uInt64 nPos, sal_uInt64 nSize)
 {
+    if (nSize < 8)
+        return false;
+
     // %PDF-x.y
     sal_uInt8 aFirstBytes[8];
-    rInStream.Seek(STREAM_SEEK_TO_BEGIN);
+    rInStream.Seek(nPos);
     sal_uLong nRead = rInStream.ReadBytes(aFirstBytes, 8);
     if (nRead < 8)
         return false;
@@ -133,13 +138,14 @@ bool isCompatible(SvStream& rInStream)
 
 /// Takes care of transparently downgrading the version of the PDF stream in
 /// case it's too new for our PDF export.
-bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
+bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream,
+                         sal_uInt64 nPos, sal_uInt64 nSize)
 {
-    bool bCompatible = isCompatible(rInStream);
-    rInStream.Seek(STREAM_SEEK_TO_BEGIN);
+    bool bCompatible = isCompatible(rInStream, nPos, nSize);
+    rInStream.Seek( nPos );
     if (bCompatible)
         // Not converting.
-        rOutStream.WriteStream(rInStream);
+        rOutStream.WriteStream(rInStream, nSize);
     else
     {
         // Downconvert to PDF-1.4.
@@ -152,7 +158,7 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
 
         // Read input into a buffer.
         SvMemoryStream aInBuffer;
-        aInBuffer.WriteStream(rInStream);
+        aInBuffer.WriteStream(rInStream, nSize);
 
         // Load the buffer using pdfium.
         FPDF_DOCUMENT pPdfDocument = FPDF_LoadMemDocument(aInBuffer.GetData(), aInBuffer.GetSize(), /*password=*/nullptr);
@@ -174,18 +180,22 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
     return rOutStream.good();
 }
 #else
-bool generatePreview(SvStream& rStream, Graphic& rGraphic)
+bool generatePreview(SvStream& rStream, Bitmap& rBitmap
+                     sal_uInt64 nPos, sal_uInt64 nSize)
 {
     (void)rStream;
-    (void)rGraphic;
+    (void)rBitmap;
+    (void)nPos;
+    (void)nSize;
 
     return true;
 }
 
-bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
+bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream,
+                         sal_uInt64 nPos, sal_uInt64 nSize)
 {
-    rInStream.Seek(STREAM_SEEK_TO_BEGIN);
-    rOutStream.WriteStream(rInStream);
+    rInStream.Seek(nPos);
+    rOutStream.WriteStream(rInStream, nSize);
     return rOutStream.good();
 }
 #endif // HAVE_FEATURE_PDFIUM
@@ -195,26 +205,38 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
 namespace vcl
 {
 
-bool ImportPDF(SvStream& rStream, Graphic& rGraphic)
+bool ImportPDF(SvStream& rStream, Bitmap &rBitmap,
+               css::uno::Sequence<sal_Int8> &rPdfData,
+               sal_uInt64 nPos, sal_uInt64 nSize)
 {
     // Get the preview of the first page.
-    if (!generatePreview(rStream, rGraphic))
+    if (!generatePreview(rStream, rBitmap, nPos, nSize))
         return false;
 
     // Save the original PDF stream for later use.
     SvMemoryStream aMemoryStream;
-    if (!getCompatibleStream(rStream, aMemoryStream))
+    if (!getCompatibleStream(rStream, aMemoryStream, nPos, nSize))
         return false;
 
     aMemoryStream.Seek(STREAM_SEEK_TO_END);
-    uno::Sequence<sal_Int8> aPdfData(aMemoryStream.Tell());
+    rPdfData = css::uno::Sequence<sal_Int8>(aMemoryStream.Tell());
     aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
-    aMemoryStream.ReadBytes(aPdfData.getArray(), aPdfData.getLength());
-    rGraphic.setPdfData(aPdfData);
+    aMemoryStream.ReadBytes(rPdfData.getArray(), rPdfData.getLength());
 
     return true;
 }
 
+
+bool ImportPDF(SvStream& rStream, Graphic& rGraphic)
+{
+    uno::Sequence<sal_Int8> aPdfData;
+    Bitmap aBitmap;
+    bool bRet = ImportPDF(rStream, aBitmap, aPdfData);
+    rGraphic = aBitmap;
+    rGraphic.setPdfData(aPdfData);
+    return bRet;
+}
+
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index b0b472c1c8d8..983eb468e238 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -41,6 +41,8 @@
 #include <o3tl/make_unique.hxx>
 #include <vcl/gdimetafiletools.hxx>
 
+#include <pdfread.hxx>
+
 #define GRAPHIC_MTFTOBMP_MAXEXT     2048
 #define GRAPHIC_STREAMBUFSIZE       8192UL
 
@@ -1574,13 +1576,14 @@ void ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic )
                 // Stream in PDF data.
                 sal_uInt32 nPdfDataLength = 0;
                 rIStm.ReadUInt32(nPdfDataLength);
+                Bitmap aBitmap;
 
-                if (nPdfDataLength)
+                if (nPdfDataLength && !rIStm.GetError() &&
+                    vcl::ImportPDF(rIStm, aBitmap, rImpGraphic.maPdfData,
+                                   rIStm.Tell(), nPdfDataLength))
                 {
-                    uno::Sequence<sal_Int8> aPdfData(nPdfDataLength);
-                    rIStm.ReadBytes(aPdfData.getArray(), nPdfDataLength);
-                    if (!rIStm.GetError())
-                        rImpGraphic.maPdfData = aPdfData;
+                    rImpGraphic.maEx = aBitmap;
+                    rImpGraphic.meType = GraphicType::Bitmap;
                 }
             }
             else


More information about the Libreoffice-commits mailing list