summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@collabora.com>2018-06-22 00:44:44 +0200
committerTomaž Vajngerl <quikee@gmail.com>2020-03-21 15:49:02 +0100
commit85e51434cf2529dfd247a9580ca749f33b602375 (patch)
tree929eafa76292092756e93c889bffa825463453e8
parent512e58a3962b403df9d995fdb4ca8d3f7c6768eb (diff)
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@gmail.com> Tested-by: Ashod Nakashian <ashnakash@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/69626 Reviewed-by: Jan Holesovsky <kendy@collabora.com> Tested-by: Jan Holesovsky <kendy@collabora.com> (cherry picked from commit 826208d2da6c92e94b38ef447e47550285742755) Reviewed-on: https://gerrit.libreoffice.org/77687 Tested-by: Jenkins (cherry picked from commit e4cec56a699b75102c39f4f80879a8080fc5ecc1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90833 Tested-by: Tomaž Vajngerl <quikee@gmail.com> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--include/vcl/pdfread.hxx5
-rw-r--r--vcl/source/filter/ipdf/pdfread.cxx128
-rw-r--r--vcl/source/gdi/impgraph.cxx40
3 files changed, 96 insertions, 77 deletions
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 9b6bf0da8d77..4e3d6c6b4be9 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -41,6 +41,7 @@
#include <com/sun/star/ucb/CommandAbortedException.hpp>
#include <com/sun/star/ucb/ContentCreationException.hpp>
#include <vcl/dibtools.hxx>
+#include <map>
#include <memory>
#include <o3tl/make_unique.hxx>
#include <vcl/gdimetafiletools.hxx>
@@ -1740,6 +1741,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 )
{
@@ -1888,23 +1890,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
{
@@ -1997,10 +2001,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())
{