filter/source/pdf/pdfdecomposer.cxx | 28 ++++++++++++++++---- include/vcl/graph.hxx | 2 - include/vcl/vectorgraphicdata.hxx | 12 +++++--- offapi/com/sun/star/graphic/XPdfDecomposer.idl | 8 +++++ sd/qa/unit/import-tests.cxx | 15 ++++++----- vcl/inc/impgraph.hxx | 7 +---- vcl/source/filter/ipdf/pdfread.cxx | 22 +++++----------- vcl/source/gdi/graph.cxx | 7 ----- vcl/source/gdi/impgraph.cxx | 34 ++++++++++--------------- vcl/source/gdi/vectorgraphicdata.cxx | 22 ++++++++++++---- 10 files changed, 87 insertions(+), 70 deletions(-)
New commits: commit 571755b3653bb06586e7cae232d1ca943719a732 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Fri Mar 13 20:04:45 2020 +0100 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Mar 23 17:18:00 2020 +0100 pdfium: support for pages when using PDF import with pdfium Moving PDF to use VectorGraphicData in Graphic has temporary removed the support for showing different PDF pages when opening the PDF using pdfium (LO_IMPORT_USE_PDFIUM=1). This adds the support for back by specifying whcih PDF page to render when creating the VectorGraphicData (and can't be changd afterwards), which is used to create a Graphic and contains the PDF source data array. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90562 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> (cherry picked from commit 27ee05f860e8225a41e15e0853fcef00a9d7a621) Change-Id: Ib915216b8d4c0c063d0fead44ff156b1915a35d2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90844 Tested-by: Tomaž Vajngerl <[email protected]> Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/filter/source/pdf/pdfdecomposer.cxx b/filter/source/pdf/pdfdecomposer.cxx index c926b1b35a9d..a03e70bd5d1a 100644 --- a/filter/source/pdf/pdfdecomposer.cxx +++ b/filter/source/pdf/pdfdecomposer.cxx @@ -39,8 +39,9 @@ public: XPdfDecomposer& operator=(const XPdfDecomposer&) = delete; // XPdfDecomposer - uno::Sequence<uno::Reference<graphic::XPrimitive2D>> - SAL_CALL getDecomposition(const uno::Sequence<sal_Int8>& xPdfData) override; + uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL + getDecomposition(const uno::Sequence<sal_Int8>& xPdfData, + const uno::Sequence<beans::PropertyValue>& xDecompositionParameters) override; // XServiceInfo OUString SAL_CALL getImplementationName() override; @@ -50,12 +51,27 @@ public: XPdfDecomposer::XPdfDecomposer(uno::Reference<uno::XComponentContext> const&) {} -uno::Sequence<uno::Reference<graphic::XPrimitive2D>> - SAL_CALL XPdfDecomposer::getDecomposition(const uno::Sequence<sal_Int8>& xPdfData) +uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL XPdfDecomposer::getDecomposition( + const uno::Sequence<sal_Int8>& xPdfData, const uno::Sequence<beans::PropertyValue>& xParameters) { + sal_Int32 nPageIndex = -1; + + for (sal_Int32 index = 0; index < xParameters.getLength(); index++) + { + const beans::PropertyValue& rProperty = xParameters[index]; + + if (rProperty.Name == "PageIndex") + { + rProperty.Value >>= nPageIndex; + } + } + + if (nPageIndex < 0) + nPageIndex = 0; + std::vector<Bitmap> aBitmaps; - vcl::RenderPDFBitmaps(xPdfData.getConstArray(), xPdfData.getLength(), aBitmaps, 0, - 1 /*, fResolutionDPI*/); + vcl::RenderPDFBitmaps(xPdfData.getConstArray(), xPdfData.getLength(), aBitmaps, nPageIndex, 1); + BitmapEx aReplacement(aBitmaps[0]); // short form for scale and translate transformation diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx index aff67351e3d9..af77fc9cad1f 100644 --- a/include/vcl/graph.hxx +++ b/include/vcl/graph.hxx @@ -227,8 +227,6 @@ public: const VectorGraphicDataPtr& getVectorGraphicData() const; - /// Set the page number of the multi-page source this Graphic is rendered from. - void setPageNumber(sal_Int32 nPageNumber); /// Get the page number of the multi-page source this Graphic is rendered from. sal_Int32 getPageNumber() const; diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx index ad402431181c..bdcfa8a9c4e0 100644 --- a/include/vcl/vectorgraphicdata.hxx +++ b/include/vcl/vectorgraphicdata.hxx @@ -69,6 +69,9 @@ private: // extra: std::unique_ptr<WmfExternal> mpExternalHeader; + // If the vector format has more pages this denotes which page to render + sal_Int32 mnPageIndex; + // on demand creators void ensurePdfReplacement(); void ensureReplacement(); @@ -81,10 +84,9 @@ public: VectorGraphicData( const VectorGraphicDataArray& rVectorGraphicDataArray, const OUString& rPath, - VectorGraphicDataType eVectorDataType); - VectorGraphicData( - const OUString& rPath, - VectorGraphicDataType eVectorDataType); + VectorGraphicDataType eVectorDataType, + sal_Int32 nPageIndex = -1); + VectorGraphicData(const OUString& rPath, VectorGraphicDataType eVectorDataType); ~VectorGraphicData(); /// compare op @@ -106,6 +108,8 @@ public: const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > >& getPrimitive2DSequence() const; const BitmapEx& getReplacement() const; BitmapChecksum GetChecksum() const; + + sal_Int32 getPageIndex() const { return mnPageIndex; } }; typedef std::shared_ptr< VectorGraphicData > VectorGraphicDataPtr; diff --git a/offapi/com/sun/star/graphic/XPdfDecomposer.idl b/offapi/com/sun/star/graphic/XPdfDecomposer.idl index 85b38c035c8c..aae6eda55347 100644 --- a/offapi/com/sun/star/graphic/XPdfDecomposer.idl +++ b/offapi/com/sun/star/graphic/XPdfDecomposer.idl @@ -27,9 +27,15 @@ interface XPdfDecomposer : ::com::sun::star::uno::XInterface @param xPdfData The PDF data. + @param xDecompositionParameters + Parameters for decomposition. Parameters include: + + sal_Int32 Page - which page to use + @since LibreOffice 7.0 */ - sequence<XPrimitive2D> getDecomposition([in] sequence<byte> xPdfData); + sequence<XPrimitive2D> getDecomposition([in] sequence<byte> xPdfData, + [in] sequence<com::sun::star::beans::PropertyValue> xDecompositionParameters); }; }; }; }; }; diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index fef49207d3ae..69a945281e95 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -1278,17 +1278,20 @@ void SdImportTest::testPDFImportShared() CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected more than one page.", size_t(3), aGraphics.size()); - Graphic aFirstGraphic = aGraphics[0]; + Graphic const & rFirstGraphic = aGraphics[0]; - for (size_t i = 1; i < aGraphics.size(); ++i) + for (size_t i = 0; i < aGraphics.size(); ++i) { + Graphic const & rGraphic = aGraphics[i]; CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected all PDF streams to be identical.", - aFirstGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray(), - aGraphics[i].getVectorGraphicData()->getVectorGraphicDataArray().getConstArray()); + rFirstGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray(), + rGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray()); CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected all GfxLinks to be identical.", - aFirstGraphic.GetSharedGfxLink().get(), - aGraphics[i].GetSharedGfxLink().get()); + rFirstGraphic.GetSharedGfxLink().get(), + rGraphic.GetSharedGfxLink().get()); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Page number doesn't match expected", sal_Int32(i), rGraphic.getPageNumber()); } xDocShRef->DoClose(); diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index 6ced13bc71f4..c01b28334ce5 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -92,11 +92,6 @@ private: std::chrono::high_resolution_clock::time_point maLastUsed; bool mbPrepared; - /// Used with GfxLink and/or PdfData when they store original media - /// which might be multi-page (PDF, f.e.) and we need to re-render - /// this Graphic (a page) from the source in GfxLink or PdfData. - sal_Int32 mnPageNumber; - public: ImpGraphic(); ImpGraphic( const ImpGraphic& rImpGraphic ); @@ -219,6 +214,8 @@ private: bool ensureAvailable () const; bool loadPrepared(); + + sal_Int32 getPageNumber() const; }; #endif // INCLUDED_VCL_INC_IMPGRAPH_HXX diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 1ad0786b8a37..2cb7907ddd5e 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -225,19 +225,12 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi bool ImportPDF(SvStream& rStream, Graphic& rGraphic) { - // Save the original PDF stream for later use. - SvMemoryStream aMemoryStream; - if (!getCompatibleStream(rStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END)) - return false; - const sal_uInt32 nStreamLength = aMemoryStream.TellEnd(); - VectorGraphicDataArray aPdfData(nStreamLength); - aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); - aMemoryStream.ReadBytes(aPdfData.begin(), nStreamLength); - if (aMemoryStream.GetError()) + VectorGraphicDataArray aPdfDataArray = createVectorGraphicDataArray(rStream); + if (!aPdfDataArray.hasElements()) return false; - auto aVectorGraphicDataPtr - = std::make_shared<VectorGraphicData>(aPdfData, OUString(), VectorGraphicDataType::Pdf); + auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aPdfDataArray, OUString(), + VectorGraphicDataType::Pdf); rGraphic = Graphic(aVectorGraphicDataPtr); return true; @@ -272,8 +265,8 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si FPDF_InitLibraryWithConfig(&aConfig); // Load the buffer using pdfium. - FPDF_DOCUMENT pPdfDocument - = FPDF_LoadMemDocument(pGfxLink->GetData(), pGfxLink->GetDataSize(), /*password=*/nullptr); + FPDF_DOCUMENT pPdfDocument = FPDF_LoadMemDocument( + aPdfDataArray.getConstArray(), aPdfDataArray.getLength(), /*password=*/nullptr); if (!pPdfDocument) return 0; @@ -293,13 +286,12 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si const size_t nPageHeight = pointToPixel(fPageHeight, fResolutionDPI); auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>( - aPdfDataArray, OUString(), VectorGraphicDataType::Pdf); + aPdfDataArray, OUString(), VectorGraphicDataType::Pdf, nPageIndex); // Create the Graphic with the VectorGraphicDataPtr and link the original PDF stream. // We swap out this Graphic as soon as possible, and a later swap in // actually renders the correct Bitmap on demand. Graphic aGraphic(aVectorGraphicDataPtr); - aGraphic.setPageNumber(nPageIndex); aGraphic.SetGfxLink(pGfxLink); rGraphics.emplace_back(std::move(aGraphic), Size(nPageWidth, nPageHeight)); diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx index d097b9c3a870..0599091f8996 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -570,14 +570,9 @@ const VectorGraphicDataPtr& Graphic::getVectorGraphicData() const return mxImpGraphic->getVectorGraphicData(); } -void Graphic::setPageNumber(sal_Int32 nPageNumber) -{ - mxImpGraphic->mnPageNumber = nPageNumber; -} - sal_Int32 Graphic::getPageNumber() const { - return mxImpGraphic->mnPageNumber; + return mxImpGraphic->getPageNumber(); } OUString Graphic::getOriginURL() const diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index 49eaa2589801..c700358312c5 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -181,8 +181,7 @@ ImpGraphic::ImpGraphic() : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared ( false ), - mnPageNumber(-1) + mbPrepared ( false ) { } @@ -201,7 +200,6 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic) , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) , maLastUsed (std::chrono::high_resolution_clock::now()) , mbPrepared (rImpGraphic.mbPrepared) - , mnPageNumber(rImpGraphic.mnPageNumber) { if( rImpGraphic.mpAnimation ) { @@ -226,7 +224,6 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) , maLastUsed (std::chrono::high_resolution_clock::now()) , mbPrepared (rImpGraphic.mbPrepared) - , mnPageNumber(rImpGraphic.mnPageNumber) { rImpGraphic.ImplClear(); rImpGraphic.mbDummyContext = false; @@ -239,8 +236,7 @@ ImpGraphic::ImpGraphic(GraphicExternalLink const & rGraphicExternalLink) : mbDummyContext ( false ), maGraphicExternalLink(rGraphicExternalLink), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -251,8 +247,7 @@ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -263,8 +258,7 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -275,8 +269,7 @@ ImpGraphic::ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr) mbDummyContext ( false ), maVectorGraphicData(rVectorGraphicDataPtr), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -288,8 +281,7 @@ ImpGraphic::ImpGraphic( const Animation& rAnimation ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -300,8 +292,7 @@ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -323,7 +314,6 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) maSwapInfo = rImpGraphic.maSwapInfo; mpContext = rImpGraphic.mpContext; mbDummyContext = rImpGraphic.mbDummyContext; - mnPageNumber = rImpGraphic.mnPageNumber; maGraphicExternalLink = rImpGraphic.maGraphicExternalLink; mpAnimation.reset(); @@ -363,7 +353,6 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic) maSwapInfo = std::move(rImpGraphic.maSwapInfo); mpContext = std::move(rImpGraphic.mpContext); mbDummyContext = rImpGraphic.mbDummyContext; - mnPageNumber = rImpGraphic.mnPageNumber; mpAnimation = std::move(rImpGraphic.mpAnimation); maEx = std::move(rImpGraphic.maEx); mbSwapOut = rImpGraphic.mbSwapOut; @@ -379,8 +368,6 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic) vcl::graphic::Manager::get().changeExisting(this, aOldSizeBytes); - rImpGraphic.mnPageNumber = -1; - return *this; } @@ -1707,6 +1694,13 @@ bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const return bResult; } +sal_Int32 ImpGraphic::getPageNumber() const +{ + if (maVectorGraphicData) + return maVectorGraphicData->getPageIndex(); + return -1; +} + static std::map<BitmapChecksum, std::shared_ptr<std::vector<sal_Int8>>> sPdfDataCache; void ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic ) diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx index 6b3debe7b589..97adf8bf317b 100644 --- a/vcl/source/gdi/vectorgraphicdata.cxx +++ b/vcl/source/gdi/vectorgraphicdata.cxx @@ -32,6 +32,7 @@ #include <vcl/canvastools.hxx> #include <comphelper/seqstream.hxx> #include <comphelper/sequence.hxx> +#include <comphelper/propertysequence.hxx> #include <vcl/svapp.hxx> #include <vcl/outdev.hxx> #include <vcl/wmfexternal.hxx> @@ -145,7 +146,10 @@ void VectorGraphicData::ensurePdfReplacement() // use PDFium directly std::vector<Bitmap> aBitmaps; - vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength(), aBitmaps, 0, 1/*, fResolutionDPI*/); + sal_Int32 nUsePageIndex = 0; + if (mnPageIndex >= 0) + nUsePageIndex = mnPageIndex; + vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength(), aBitmaps, nUsePageIndex, 1/*, fResolutionDPI*/); maReplacement = aBitmaps[0]; } @@ -200,7 +204,9 @@ void VectorGraphicData::ensureSequenceAndRange() uno::Sequence< ::beans::PropertyValue > aSequence; if (mpExternalHeader) + { aSequence = mpExternalHeader->getSequence(); + } if (myInputStream.is()) maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence)); @@ -210,7 +216,10 @@ void VectorGraphicData::ensureSequenceAndRange() case VectorGraphicDataType::Pdf: { const uno::Reference<graphic::XPdfDecomposer> xPdfDecomposer = graphic::PdfTools::create(xContext); - auto xPrimitive2D = xPdfDecomposer->getDecomposition(maVectorGraphicDataArray); + uno::Sequence<beans::PropertyValue> aDecompositionParameters = comphelper::InitPropertySequence({ + {"PageIndex", uno::makeAny<sal_Int32>(mnPageIndex)}, + }); + auto xPrimitive2D = xPdfDecomposer->getDecomposition(maVectorGraphicDataArray, aDecompositionParameters); maSequence = comphelper::sequenceToContainer<std::deque<uno::Reference<graphic::XPrimitive2D>>>(xPrimitive2D); break; @@ -261,7 +270,8 @@ auto VectorGraphicData::getSizeBytes() -> std::pair<State, size_t> VectorGraphicData::VectorGraphicData( const VectorGraphicDataArray& rVectorGraphicDataArray, const OUString& rPath, - VectorGraphicDataType eVectorDataType) + VectorGraphicDataType eVectorDataType, + sal_Int32 nPageIndex) : maVectorGraphicDataArray(rVectorGraphicDataArray), maPath(rPath), mbSequenceCreated(false), @@ -269,7 +279,8 @@ VectorGraphicData::VectorGraphicData( maSequence(), maReplacement(), mNestedBitmapSize(0), - meVectorGraphicDataType(eVectorDataType) + meVectorGraphicDataType(eVectorDataType), + mnPageIndex(nPageIndex) { } @@ -283,7 +294,8 @@ VectorGraphicData::VectorGraphicData( maSequence(), maReplacement(), mNestedBitmapSize(0), - meVectorGraphicDataType(eVectorDataType) + meVectorGraphicDataType(eVectorDataType), + mnPageIndex(-1) { SvFileStream rIStm(rPath, StreamMode::STD_READ); if(rIStm.GetError()) _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
