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 | 18 +++---------- vcl/source/gdi/graph.cxx | 7 ----- vcl/source/gdi/impgraph.cxx | 34 ++++++++++--------------- vcl/source/gdi/vectorgraphicdata.cxx | 22 ++++++++++++---- 10 files changed, 85 insertions(+), 68 deletions(-)
New commits: commit 27ee05f860e8225a41e15e0853fcef00a9d7a621 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Mar 13 20:04:45 2020 +0100 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Wed Mar 18 09:23:15 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. Change-Id: Ib915216b8d4c0c063d0fead44ff156b1915a35d2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90562 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> 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 271de60d1605..6e70f66731ac 100644 --- a/include/vcl/graph.hxx +++ b/include/vcl/graph.hxx @@ -204,8 +204,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 096c89e1aa56..8ccf45b51e5d 100644 --- a/include/vcl/vectorgraphicdata.hxx +++ b/include/vcl/vectorgraphicdata.hxx @@ -70,6 +70,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(); @@ -82,10 +85,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 @@ -107,6 +109,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 addf393630a1..954ef5b187ba 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -1327,17 +1327,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 965c41a4392e..a5435ee73b39 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -75,11 +75,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 ); @@ -203,6 +198,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 0dbb0fe455cb..b85a79d86e4a 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -223,19 +223,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; @@ -291,13 +284,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 c98212ad5c67..96414b43ad3a 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -560,14 +560,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 9361aef3951d..90a1e4e58ed8 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -73,8 +73,7 @@ ImpGraphic::ImpGraphic() : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared ( false ), - mnPageNumber(-1) + mbPrepared ( false ) { } @@ -93,7 +92,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 ) { @@ -118,7 +116,6 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) noexcept , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) , maLastUsed (std::chrono::high_resolution_clock::now()) , mbPrepared (rImpGraphic.mbPrepared) - , mnPageNumber(rImpGraphic.mnPageNumber) { rImpGraphic.ImplClear(); rImpGraphic.mbDummyContext = false; @@ -131,8 +128,7 @@ ImpGraphic::ImpGraphic(GraphicExternalLink const & rGraphicExternalLink) : mbDummyContext ( false ), maGraphicExternalLink(rGraphicExternalLink), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -143,8 +139,7 @@ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -155,8 +150,7 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -167,8 +161,7 @@ ImpGraphic::ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr) mbDummyContext ( false ), maVectorGraphicData(rVectorGraphicDataPtr), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -180,8 +173,7 @@ ImpGraphic::ImpGraphic( const Animation& rAnimation ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -192,8 +184,7 @@ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) : mbSwapOut ( false ), mbDummyContext ( false ), maLastUsed (std::chrono::high_resolution_clock::now()), - mbPrepared (false), - mnPageNumber(-1) + mbPrepared (false) { } @@ -215,7 +206,6 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) maSwapInfo = rImpGraphic.maSwapInfo; mpContext = rImpGraphic.mpContext; mbDummyContext = rImpGraphic.mbDummyContext; - mnPageNumber = rImpGraphic.mnPageNumber; maGraphicExternalLink = rImpGraphic.maGraphicExternalLink; mpAnimation.reset(); @@ -255,7 +245,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; @@ -271,8 +260,6 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic) vcl::graphic::Manager::get().changeExisting(this, aOldSizeBytes); - rImpGraphic.mnPageNumber = -1; - return *this; } @@ -1618,6 +1605,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 9d877b35a73a..99e51f65cc71 100644 --- a/vcl/source/gdi/vectorgraphicdata.cxx +++ b/vcl/source/gdi/vectorgraphicdata.cxx @@ -33,6 +33,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> @@ -146,7 +147,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]; } @@ -201,7 +205,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)); @@ -211,7 +217,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; @@ -262,7 +271,8 @@ auto VectorGraphicData::getSizeBytes() const -> 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), @@ -270,7 +280,8 @@ VectorGraphicData::VectorGraphicData( maSequence(), maReplacement(), mNestedBitmapSize(0), - meVectorGraphicDataType(eVectorDataType) + meVectorGraphicDataType(eVectorDataType), + mnPageIndex(nPageIndex) { } @@ -284,7 +295,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 libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits