diff options
-rw-r--r-- | include/vcl/pdfread.hxx | 34 | ||||
-rw-r--r-- | sd/source/filter/pdf/sdpdffilter.cxx | 34 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 73 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 7 |
4 files changed, 121 insertions, 27 deletions
diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index c31251bfaf53..f3956eba5384 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -10,8 +10,26 @@ #ifndef INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX #define INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX +#include <vector> #include <tools/stream.hxx> #include <vcl/graph.hxx> +#include <tools/gen.hxx> + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace uno +{ +template <typename> class Sequence; +} +} +} +} +class Bitmap; +class Graphic; namespace vcl { @@ -22,9 +40,8 @@ VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vecto 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> &rPdfFata, +VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex, + css::uno::Sequence<sal_Int8>& rPdfData, sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN, sal_uInt64 nSize = STREAM_SEEK_TO_END, const double fResolutionDPI = 96.); @@ -32,10 +49,17 @@ VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap &rBitmap, VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic, const double fResolutionDPI = 96.); -VCL_DLLPUBLIC size_t ImportPDF(const OUString& rURL, - std::vector<Bitmap>& rBitmaps, +VCL_DLLPUBLIC size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps, css::uno::Sequence<sal_Int8>& rPdfData, const double fResolutionDPI = 96.); + +/// Import PDF as Graphic images (1 per page), all unloaded. +/// Since Graphic is unloaded, we need to return the page size (in pixels) separately. +/// Does not set rPdfData if no conversion is done. +/// Returns the number of pages read. +VCL_DLLPUBLIC size_t ImportPDFUnloaded(const OUString& rURL, + std::vector<std::pair<Graphic, Size>>& rGraphics, + const double fResolutionDPI = 96.); } #endif // INCLUDED_VCL_SOURCE_FILTER_IPDF_PDFREAD_HXX diff --git a/sd/source/filter/pdf/sdpdffilter.cxx b/sd/source/filter/pdf/sdpdffilter.cxx index 8ca237fd6345..62dbc3964f35 100644 --- a/sd/source/filter/pdf/sdpdffilter.cxx +++ b/sd/source/filter/pdf/sdpdffilter.cxx @@ -102,37 +102,29 @@ bool SdPdfFilter::Import() // Rendering resolution. const double dResolutionDPI = 96.; - uno::Sequence<sal_Int8> aPdfData; - std::vector<Bitmap> aBitmaps; - if (vcl::ImportPDF(aFileName, aBitmaps, aPdfData, dResolutionDPI) == 0) + std::vector<std::pair<Graphic, Size>> aGraphics; + if (vcl::ImportPDFUnloaded(aFileName, aGraphics, dResolutionDPI) == 0) return false; - // Prepare the link with the PDF stream. - const size_t nGraphicContentSize = aPdfData.getLength(); - std::unique_ptr<sal_uInt8[]> pGraphicContent(new sal_uInt8[nGraphicContentSize]); - memcpy(pGraphicContent.get(), aPdfData.get(), nGraphicContentSize); - std::shared_ptr<GfxLink> pGfxLink = std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, GfxLinkType::NativePdf); - auto pPdfData = std::make_shared<uno::Sequence<sal_Int8>>(aPdfData); - + // Add as many pages as we need up-front. mrDocument.CreateFirstPages(); - for (size_t i = 0; i < aBitmaps.size() - 1; ++i) + for (int i = 0; i < aGraphics.size() - 1; ++i) { mrDocument.DuplicatePage(0); } - size_t nPageNumber = 0; - for (Bitmap& aBitmap : aBitmaps) + for (std::pair<Graphic, Size>& aPair : aGraphics) { - // Create the Graphic and link the original PDF stream. - Graphic aGraphic(aBitmap); - aGraphic.setPdfData(pPdfData); - aGraphic.setPageNumber(nPageNumber); - aGraphic.SetSharedLink(pGfxLink); - aGraphic.setOriginURL(aFileName); + const Graphic& aGraphic = aPair.first; + const Size& aSize = aPair.second; + + const sal_Int32 nPageNumber = aGraphic.getPageNumber(); + if (nPageNumber < 0 || nPageNumber >= aGraphics.size()) + continue; // Page is out of range // Create the page and insert the Graphic. - SdPage* pPage = mrDocument.GetSdPage(nPageNumber++, PageKind::Standard); - Size aGrfSize(OutputDevice::LogicToLogic(aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), + SdPage* pPage = mrDocument.GetSdPage(nPageNumber, PageKind::Standard); + Size aGrfSize(OutputDevice::LogicToLogic(aSize, aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM))); // Resize to original size based on 72 dpi to preserve page size. diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 2e9d7c4909d7..e92b0c7b54a3 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -23,8 +23,10 @@ #endif #endif -#include <vcl/bitmapaccess.hxx> +#include <impgraph.hxx> + #include <vcl/graph.hxx> +#include <vcl/bitmapaccess.hxx> #include <unotools/ucbstreamhelper.hxx> using namespace com::sun::star; @@ -302,6 +304,75 @@ size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps, return rBitmaps.size(); } + +size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Size>>& rGraphics, + const double fResolutionDPI) +{ + std::unique_ptr<SvStream> xStream( + ::utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ | StreamMode::SHARE_DENYNONE)); + + // Save the original PDF stream for later use. + SvMemoryStream aMemoryStream; + if (!getCompatibleStream(*xStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END)) + return 0; + + // Copy into PdfData + uno::Sequence<sal_Int8> aPdfData; + aMemoryStream.Seek(STREAM_SEEK_TO_END); + aPdfData = css::uno::Sequence<sal_Int8>(aMemoryStream.Tell()); + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + aMemoryStream.ReadBytes(aPdfData.getArray(), aPdfData.getLength()); + + // Prepare the link with the PDF stream. + const size_t nGraphicContentSize = aPdfData.getLength(); + std::unique_ptr<sal_uInt8[]> pGraphicContent(new sal_uInt8[nGraphicContentSize]); + memcpy(pGraphicContent.get(), aPdfData.get(), nGraphicContentSize); + std::shared_ptr<GfxLink> pGfxLink(std::make_shared<GfxLink>( + std::move(pGraphicContent), nGraphicContentSize, GfxLinkType::NativePdf)); + auto pPdfData = std::make_shared<uno::Sequence<sal_Int8>>(aPdfData); + + 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(aPdfData.getArray(), aPdfData.getLength(), /*password=*/nullptr); + if (!pPdfDocument) + return 0; + + const int nPageCount = FPDF_GetPageCount(pPdfDocument); + if (nPageCount <= 0) + return 0; + + for (size_t nPageIndex = 0; nPageIndex < static_cast<size_t>(nPageCount); ++nPageIndex) + { + double fPageWidth = 0; + double fPageHeight = 0; + if (FPDF_GetPageSizeByIndex(pPdfDocument, nPageIndex, &fPageWidth, &fPageHeight) == 0) + continue; + + // Returned unit is points, convert that to pixel. + const size_t nPageWidth = pointToPixel(fPageWidth, fResolutionDPI); + const size_t nPageHeight = pointToPixel(fPageHeight, fResolutionDPI); + + // Create the Graphic and link the original PDF stream. + Graphic aGraphic; + aGraphic.setPdfData(pPdfData); // TODO: Skip if unchanged. + aGraphic.setPageNumber(nPageIndex); + aGraphic.SetSharedLink(pGfxLink); + + rGraphics.emplace_back(std::move(aGraphic), Size(nPageWidth, nPageHeight)); + } + + FPDF_CloseDocument(pPdfDocument); + FPDF_DestroyLibrary(); + + return rGraphics.size(); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index d2106041f9cd..cdad0f51e457 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -1371,7 +1371,14 @@ void ImpGraphic::ImplSetSharedLink(const std::shared_ptr<GfxLink>& pGfxLink) mpGfxLink = pGfxLink; if (mpGfxLink->IsNative()) + { mpGfxLink->SwapOut(); + + // Swap out the graphic as well. + //FIXME: move to own function, such as SetPrepared(). + meType = GraphicType::Bitmap; + ImplSwapOut(); + } } GfxLink ImpGraphic::ImplGetLink() |