diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-10-26 16:05:54 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-11-06 15:49:20 +0100 |
commit | 3a88795c1211c62277dc646e61c2ba8306febe37 (patch) | |
tree | ba44aef0c3dd0f8e1653759bd5cb86d1adae212a /vcl | |
parent | a4b7c54ea83e354f3dae3165bd71989a796ed6bc (diff) |
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@libreoffice.org>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/pdfread.hxx (renamed from vcl/source/filter/ipdf/pdfread.hxx) | 4 | ||||
-rw-r--r-- | vcl/source/filter/graphicfilter.cxx | 2 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 66 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 13 |
4 files changed, 57 insertions, 28 deletions
diff --git a/vcl/source/filter/ipdf/pdfread.hxx b/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 |