include/svx/xmlgrhlp.hxx | 12 ++ include/vcl/gfxlink.hxx | 2 include/vcl/graphicfilter.hxx | 15 ++- include/vcl/pdfread.hxx | 5 - include/xmloff/xmlimp.hxx | 3 offapi/com/sun/star/document/XGraphicStorageHandler.idl | 4 sc/source/ui/view/cellsh1.cxx | 10 +- schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng | 9 ++ svx/source/xml/xmlgrhlp.cxx | 49 ++++++++++-- vcl/inc/impgraph.hxx | 2 vcl/source/filter/graphicfilter.cxx | 21 +++-- vcl/source/filter/ipdf/pdfread.cxx | 11 +- vcl/source/gdi/gfxlink.cxx | 6 - vcl/source/gdi/impgraph.cxx | 2 xmloff/qa/unit/data/two-pages.pdf |binary xmloff/qa/unit/draw.cxx | 45 +++++++++++ xmloff/source/core/xmlimp.cxx | 5 - xmloff/source/draw/shapeexport.cxx | 17 +++- xmloff/source/draw/ximpshap.cxx | 14 ++- xmloff/source/draw/ximpshap.hxx | 1 20 files changed, 182 insertions(+), 51 deletions(-)
New commits: commit 6d8d9100b043db4f7e4d828261142c3271b81fd5 Author: Gökay Şatır <gokaysa...@collabora.com> AuthorDate: Thu Nov 21 15:19:01 2024 +0300 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Feb 4 12:55:42 2025 +0100 cool#10533 LOK: Do not set the pasteMode when the view is read only. There is a chance to paste the copied content in read only view if user acts too fast. We need to set the pasteMode selectively to ensure that the action is not performed. Change-Id: I446469a2f1fa25c5cdf6c5958f664a46d6d1a741 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181085 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index f94f19ac7c48..fcbd50bcea60 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -1443,7 +1443,10 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) weld::WaitObject aWait( GetViewData().GetDialogParent() ); pTabViewShell->CopyToClip( nullptr, false, false, true ); rReq.Done(); - GetViewData().SetPasteMode( ScPasteFlags::Mode | ScPasteFlags::Border ); + + if (!comphelper::LibreOfficeKit::isActive() || !pTabViewShell->GetViewShell() || !pTabViewShell->GetViewShell()->IsLokReadOnlyView()) + GetViewData().SetPasteMode( ScPasteFlags::Mode | ScPasteFlags::Border ); + pTabViewShell->ShowCursor(); pTabViewShell->UpdateCopySourceOverlay(); } @@ -1454,7 +1457,10 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) weld::WaitObject aWait( GetViewData().GetDialogParent() ); pTabViewShell->CutToClip(); rReq.Done(); - GetViewData().SetPasteMode( ScPasteFlags::Mode | ScPasteFlags::Border ); + + if (!comphelper::LibreOfficeKit::isActive() || !pTabViewShell->GetViewShell() || !pTabViewShell->GetViewShell()->IsLokReadOnlyView()) + GetViewData().SetPasteMode( ScPasteFlags::Mode | ScPasteFlags::Border ); + pTabViewShell->ShowCursor(); pTabViewShell->UpdateCopySourceOverlay(); } commit 87f132a5e81557e423456c12c1bdcde13d1e4c66 Author: Jaume Pujantell <jaume.pujant...@collabora.com> AuthorDate: Tue Jan 28 10:13:11 2025 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Feb 4 12:55:29 2025 +0100 [API CHANGE] sd pdfium: add page number when saving/loading pdf pages as images When a pdf file is opened with pdfium and then saved as odg, each page is saved as a draw:image of the pdf. But since no page number info was given, when opening the odg file, all the pages are shown as the first one. This adds a loext:page-number to the saved odg and the logic to load a specific page from an embedded pdf. Added loadGraphicAtPage to XGraphicStorageHandler. Change-Id: I398b7ad7f03cc7fb930a4e7b7620c6f238b41c0d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181066 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/include/svx/xmlgrhlp.hxx b/include/svx/xmlgrhlp.hxx index 177d1afc4be6..6e84eb340e56 100644 --- a/include/svx/xmlgrhlp.hxx +++ b/include/svx/xmlgrhlp.hxx @@ -56,7 +56,8 @@ private: std::vector< css::uno::Reference< css::io::XOutputStream > > maGrfStms; - std::unordered_map<OUString, css::uno::Reference<css::graphic::XGraphic>> maGraphicObjects; + std::unordered_map<OUString, std::vector<css::uno::Reference<css::graphic::XGraphic>>> + maGraphicObjects; std::unordered_map<Graphic, std::pair<OUString, OUString>> maExportGraphics; SvXMLGraphicHelperMode meCreateMode; @@ -71,8 +72,9 @@ private: ImplGetGraphicStream( const OUString& rPictureStorageName, const OUString& rPictureStreamName ); SVX_DLLPRIVATE static OUString ImplGetGraphicMimeType( std::u16string_view rFileName ); - SVX_DLLPRIVATE Graphic ImplReadGraphic( const OUString& rPictureStorageName, - const OUString& rPictureStreamName ); + SVX_DLLPRIVATE Graphic ImplReadGraphic(const OUString& rPictureStorageName, + const OUString& rPictureStreamName, + sal_Int32 nPage = -1); SvXMLGraphicHelper(); virtual ~SvXMLGraphicHelper() override; @@ -101,6 +103,10 @@ public: virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphic(OUString const & aURL) override; + // XGraphicStorageHandler + virtual css::uno::Reference<css::graphic::XGraphic> + SAL_CALL loadGraphicAtPage(OUString const& aURL, sal_Int32 nPage) override; + virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphicFromOutputStream(css::uno::Reference<css::io::XOutputStream> const & rxOutputStream) override; diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx index 531633b3f738..1f0e0cf99f53 100644 --- a/include/vcl/gfxlink.hxx +++ b/include/vcl/gfxlink.hxx @@ -103,7 +103,7 @@ public: bool IsNative() const; - bool LoadNative( Graphic& rGraphic ) const; + bool LoadNative(Graphic& rGraphic, sal_Int32 nPageNum = -1) const; bool ExportNative( SvStream& rOStream ) const; diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx index 293e2720b76f..140fdaacff9c 100644 --- a/include/vcl/graphicfilter.hxx +++ b/include/vcl/graphicfilter.hxx @@ -272,10 +272,11 @@ public: sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat); - ErrCode ImportGraphic( Graphic& rGraphic, std::u16string_view rPath, - SvStream& rStream, - sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW, - sal_uInt16 * pDeterminedFormat = nullptr, GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE ); + ErrCode ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, SvStream& rStream, + sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW, + sal_uInt16* pDeterminedFormat = nullptr, + GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE, + sal_Int32 nPageNum = -1); /// Imports multiple graphics. /// @@ -289,7 +290,8 @@ public: void MakeGraphicsAvailableThreaded(std::vector< Graphic* >& rGraphics); // Setting sizeLimit limits how much will be read from the stream. - Graphic ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit = 0, const Size* pSizeHint = nullptr); + Graphic ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit = 0, + const Size* pSizeHint = nullptr, sal_Int32 nPage = -1); const ErrCode& GetLastError() const { return *mxErrorEx;} SAL_DLLPRIVATE void ResetLastError(); @@ -317,7 +319,8 @@ public: SAL_DLLPRIVATE static ErrCode readWMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); SAL_DLLPRIVATE static ErrCode readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); - SAL_DLLPRIVATE static ErrCode readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); + SAL_DLLPRIVATE static ErrCode readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, + sal_Int32 nPageIndex = -1); SAL_DLLPRIVATE static ErrCode readTIFF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); SAL_DLLPRIVATE static ErrCode readWithTypeSerializer(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, std::u16string_view aFilterName); SAL_DLLPRIVATE static ErrCode readBMP(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType); diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index 00b6b44969c1..894cf8af0d85 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -31,10 +31,11 @@ VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, /// Imports a PDF stream as a VectorGraphicData. VCL_DLLPUBLIC bool importPdfVectorGraphicData(SvStream& rStream, - std::shared_ptr<VectorGraphicData>& rVectorGraphicData); + std::shared_ptr<VectorGraphicData>& rVectorGraphicData, + sal_Int32 nPageIndex = -1); /// Imports a PDF stream into rGraphic. -VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic); +VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex = -1); // When inserting a PDF file as an image or pasting PDF data from the clipboard, at least on a // Retina iMac, the resulting rendered image does not look sharp without this surprisingly large diff --git a/include/xmloff/xmlimp.hxx b/include/xmloff/xmlimp.hxx index f963bd791715..44a97ddb9c3f 100644 --- a/include/xmloff/xmlimp.hxx +++ b/include/xmloff/xmlimp.hxx @@ -407,7 +407,8 @@ public: mxNumberFormatsSupplier = _xNumberFormatSupplier; } - css::uno::Reference<css::graphic::XGraphic> loadGraphicByURL(OUString const & rURL); + css::uno::Reference<css::graphic::XGraphic> loadGraphicByURL(OUString const& rURL, + sal_Int32 nPageNum = -1); css::uno::Reference<css::graphic::XGraphic> loadGraphicFromBase64(css::uno::Reference<css::io::XOutputStream> const & rxOutputStream); css::uno::Reference< css::io::XOutputStream > GetStreamForGraphicObjectURLFromBase64() const; diff --git a/offapi/com/sun/star/document/XGraphicStorageHandler.idl b/offapi/com/sun/star/document/XGraphicStorageHandler.idl index b36379890243..7390b189394f 100644 --- a/offapi/com/sun/star/document/XGraphicStorageHandler.idl +++ b/offapi/com/sun/star/document/XGraphicStorageHandler.idl @@ -21,6 +21,10 @@ interface XGraphicStorageHandler : com::sun::star::uno::XInterface */ com::sun::star::graphic::XGraphic loadGraphic([in] string aURL); + /** load a specific page from a graphic defined by the URL from the storage + */ + com::sun::star::graphic::XGraphic loadGraphicAtPage([in] string aURL, [in] long nPage); + /** load a graphic from the output stream */ com::sun::star::graphic::XGraphic loadGraphicFromOutputStream([in] com::sun::star::io::XOutputStream xOutputStream); diff --git a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng index 79bb67d7da17..6a8e3149c66e 100644 --- a/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng +++ b/schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng @@ -4025,4 +4025,13 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. </rng:attribute> </rng:optional> </rng:define> + + <!-- TODO no proposal for page number on multipage formats --> + <rng:define name="draw-image-attlist" combine="interleave"> + <rng:optional> + <rng:attribute name="loext:page-number"> + <rng:ref name="integer"/> + </rng:attribute> + </rng:optional> + </rng:define> </rng:grammar> diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx index f67f7c7c3703..e6cc29db7bfa 100644 --- a/svx/source/xml/xmlgrhlp.cxx +++ b/svx/source/xml/xmlgrhlp.cxx @@ -491,8 +491,8 @@ OUString SvXMLGraphicHelper::ImplGetGraphicMimeType( std::u16string_view rFileNa return OUString(); } -Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName, - const OUString& rPictureStreamName ) +Graphic SvXMLGraphicHelper::ImplReadGraphic(const OUString& rPictureStorageName, + const OUString& rPictureStreamName, sal_Int32 nPage) { Graphic aReturnGraphic; SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName ) ); @@ -500,11 +500,12 @@ Graphic SvXMLGraphicHelper::ImplReadGraphic( const OUString& rPictureStorageName { GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter(); std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(aStream.xStream)); - Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(*pStream); + Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(*pStream, 0, nullptr, nPage); if (!aGraphic.IsNone()) aReturnGraphic = std::move(aGraphic); else - rGraphicFilter.ImportGraphic(aReturnGraphic, u"", *pStream); + rGraphicFilter.ImportGraphic(aReturnGraphic, u"", *pStream, GRFILTER_FORMAT_DONTKNOW, + nullptr, GraphicFilterImportFlags::NONE, nPage); } return aReturnGraphic; @@ -566,6 +567,13 @@ OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const OUString& / // XGraphicStorageHandler uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicHelper::loadGraphic(OUString const & rURL) +{ + return loadGraphicAtPage(rURL, -1); +} + +// XGraphicStorageHandler +uno::Reference<graphic::XGraphic> + SAL_CALL SvXMLGraphicHelper::loadGraphicAtPage(OUString const& rURL, sal_Int32 nPage) { std::unique_lock aGuard(m_aMutex); @@ -575,22 +583,36 @@ uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicHelper::loadGraphic(OUStr OUString aUserData; splitUserDataFromURL(rURL, aURLOnly, aUserData); + size_t nIndex = (nPage >= 0 ? nPage : 0); auto aIterator = maGraphicObjects.find(aURLOnly); - if (aIterator != maGraphicObjects.end()) + if (aIterator != maGraphicObjects.end() && aIterator->second.size() > nIndex + && aIterator->second[nIndex].is()) { - return aIterator->second; + return aIterator->second[nIndex]; } OUString aPictureStorageName, aPictureStreamName; if (ImplGetStreamNames(aURLOnly, aPictureStorageName, aPictureStreamName)) { - const GraphicObject aGraphicObject(ImplReadGraphic(aPictureStorageName, aPictureStreamName)); + const GraphicObject aGraphicObject( + ImplReadGraphic(aPictureStorageName, aPictureStreamName, nPage)); if (aGraphicObject.GetType() != GraphicType::NONE) { xGraphic = aGraphicObject.GetGraphic().GetXGraphic(); - maGraphicObjects[aURLOnly] = xGraphic; + if (aIterator != maGraphicObjects.end()) + { + if (aIterator->second.size() <= nIndex) + aIterator->second.resize(nIndex + 1); + aIterator->second[nIndex] = xGraphic; + } + else + { + maGraphicObjects.emplace( + aURLOnly, std::vector<uno::Reference<graphic::XGraphic>>(nIndex + 1)); + maGraphicObjects[aURLOnly][nIndex] = xGraphic; + } } } @@ -958,6 +980,10 @@ protected: virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphic(const OUString& aURL) override; + // ____ XGraphicStorageHandler ____ + virtual css::uno::Reference<css::graphic::XGraphic> + SAL_CALL loadGraphicAtPage(const OUString& aURL, sal_Int32 nPage) override; + virtual css::uno::Reference<css::graphic::XGraphic> SAL_CALL loadGraphicFromOutputStream(css::uno::Reference<css::io::XOutputStream> const & rxOutputStream) override; @@ -1021,6 +1047,13 @@ uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicImportExportHelper::loadG return m_xXMLGraphicHelper->loadGraphic(rURL); } +// ____ XGraphicStorageHandler ____ +uno::Reference<graphic::XGraphic> SAL_CALL +SvXMLGraphicImportExportHelper::loadGraphicAtPage(OUString const& rURL, sal_Int32 nPage) +{ + return m_xXMLGraphicHelper->loadGraphicAtPage(rURL, nPage); +} + uno::Reference<graphic::XGraphic> SAL_CALL SvXMLGraphicImportExportHelper::loadGraphicFromOutputStream(uno::Reference<io::XOutputStream> const & rxOutputStream) { return m_xXMLGraphicHelper->loadGraphicFromOutputStream(rxOutputStream); diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index cad519c87e5c..3d93621e9978 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -40,7 +40,7 @@ struct ImpSwapInfo bool mbIsAlpha; sal_uInt32 mnAnimationLoopCount; - sal_Int32 mnPageIndex; + sal_Int32 mnPageIndex = -1; }; class OutputDevice; diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx index af9b2b774b4b..b72faf93da2f 100644 --- a/vcl/source/filter/graphicfilter.cxx +++ b/vcl/source/filter/graphicfilter.cxx @@ -820,7 +820,7 @@ ErrCode prepareImageTypeAndData(SvStream& rStream, sal_uInt32 nStreamLength, Bin } // end anonymous namespace Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 sizeLimit, - const Size* pSizeHint) + const Size* pSizeHint, sal_Int32 nPage) { Graphic aGraphic; sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW; @@ -877,8 +877,10 @@ Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 size pSizeHint = &aLogicSize; } } - - aGraphic.SetGfxLink(std::make_shared<GfxLink>(aBinaryDataContainer, eLinkType)); + if (eLinkType == GfxLinkType::NativePdf && nPage >= 0) + aGraphic = Graphic(std::make_shared<GfxLink>(aBinaryDataContainer, eLinkType), nPage); + else + aGraphic.SetGfxLink(std::make_shared<GfxLink>(aBinaryDataContainer, eLinkType)); aGraphic.ImplGetImpGraphic()->setPrepared(bAnimated, pSizeHint); } } @@ -1087,9 +1089,10 @@ ErrCode GraphicFilter::readEMF(SvStream & rStream, Graphic & rGraphic, GfxLinkTy return readWMF_EMF(rStream, rGraphic, rLinkType, VectorGraphicDataType::Emf); } -ErrCode GraphicFilter::readPDF(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType) +ErrCode GraphicFilter::readPDF(SvStream& rStream, Graphic& rGraphic, GfxLinkType& rLinkType, + sal_Int32 nPageIndex) { - if (vcl::ImportPDF(rStream, rGraphic)) + if (vcl::ImportPDF(rStream, rGraphic, nPageIndex)) { rLinkType = GfxLinkType::NativePdf; return ERRCODE_NONE; @@ -1246,8 +1249,10 @@ ErrCode GraphicFilter::readWEBP(SvStream & rStream, Graphic & rGraphic, GfxLinkT return ERRCODE_GRFILTER_FILTERERROR; } -ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, SvStream& rIStream, - sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, GraphicFilterImportFlags nImportFlags) +ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPath, + SvStream& rIStream, sal_uInt16 nFormat, + sal_uInt16* pDeterminedFormat, + GraphicFilterImportFlags nImportFlags, sal_Int32 nPageIndex) { OUString aFilterName; sal_uInt64 nStreamBegin; @@ -1338,7 +1343,7 @@ ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPat } else if (aFilterName.equalsIgnoreAsciiCase(IMP_PDF)) { - nStatus = readPDF(rIStream, rGraphic, eLinkType); + nStatus = readPDF(rIStream, rGraphic, eLinkType, nPageIndex); } else if (aFilterName.equalsIgnoreAsciiCase(IMP_TIFF) ) { diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 584497a9cb77..1a1bf2217f1a 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -102,7 +102,8 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<BitmapEx>& r } bool importPdfVectorGraphicData(SvStream& rStream, - std::shared_ptr<VectorGraphicData>& rVectorGraphicData) + std::shared_ptr<VectorGraphicData>& rVectorGraphicData, + sal_Int32 nPageIndex) { BinaryDataContainer aDataContainer = vcl::pdf::createBinaryDataContainer(rStream); if (aDataContainer.isEmpty()) @@ -111,16 +112,16 @@ bool importPdfVectorGraphicData(SvStream& rStream, return false; } - rVectorGraphicData - = std::make_shared<VectorGraphicData>(aDataContainer, VectorGraphicDataType::Pdf); + rVectorGraphicData = std::make_shared<VectorGraphicData>( + aDataContainer, VectorGraphicDataType::Pdf, nPageIndex); return true; } -bool ImportPDF(SvStream& rStream, Graphic& rGraphic) +bool ImportPDF(SvStream& rStream, Graphic& rGraphic, sal_Int32 nPageIndex) { std::shared_ptr<VectorGraphicData> pVectorGraphicData; - if (!importPdfVectorGraphicData(rStream, pVectorGraphicData)) + if (!importPdfVectorGraphicData(rStream, pVectorGraphicData, nPageIndex)) return false; rGraphic = Graphic(pVectorGraphicData); return true; diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx index c6ca4678b007..aff0e9778980 100644 --- a/vcl/source/gdi/gfxlink.cxx +++ b/vcl/source/gdi/gfxlink.cxx @@ -101,7 +101,7 @@ void GfxLink::SetPrefMapMode( const MapMode& rPrefMapMode ) mbPrefMapModeValid = true; } -bool GfxLink::LoadNative( Graphic& rGraphic ) const +bool GfxLink::LoadNative(Graphic& rGraphic, sal_Int32 nPageNum) const { bool bRet = false; @@ -132,7 +132,9 @@ bool GfxLink::LoadNative( Graphic& rGraphic ) const { GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); sal_uInt16 nFormat = rFilter.GetImportFormatNumberForShortName(aShortName); - ErrCode nResult = rFilter.ImportGraphic(rGraphic, u"", aMemoryStream, nFormat); + ErrCode nResult + = rFilter.ImportGraphic(rGraphic, u"", aMemoryStream, nFormat, nullptr, + GraphicFilterImportFlags::NONE, nPageNum); if (nResult == ERRCODE_NONE) bRet = true; } diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index 347dd5dc651b..59ceacee7a04 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -1463,7 +1463,7 @@ bool ImpGraphic::swapIn() if (mbPrepared) { Graphic aGraphic; - if (!mpGfxLink->LoadNative(aGraphic)) + if (!mpGfxLink->LoadNative(aGraphic, getPageNumber())) return false; updateFromLoadedGraphic(aGraphic.ImplGetImpGraphic()); diff --git a/xmloff/qa/unit/data/two-pages.pdf b/xmloff/qa/unit/data/two-pages.pdf new file mode 100644 index 000000000000..838c2d3232b1 Binary files /dev/null and b/xmloff/qa/unit/data/two-pages.pdf differ diff --git a/xmloff/qa/unit/draw.cxx b/xmloff/qa/unit/draw.cxx index 2d1a4c533f24..41019fbeb204 100644 --- a/xmloff/qa/unit/draw.cxx +++ b/xmloff/qa/unit/draw.cxx @@ -23,8 +23,10 @@ #include <com/sun/star/text/GraphicCrop.hpp> #include <comphelper/propertyvalue.hxx> +#include <comphelper/scopeguard.hxx> #include <comphelper/sequence.hxx> #include <comphelper/sequenceashashmap.hxx> +#include <osl/process.h> #include <unotools/tempfile.hxx> #include <unotools/saveopt.hxx> #include <svx/unopage.hxx> @@ -1084,6 +1086,49 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testTdf161483_CircleStartEndAngle) } } +CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testPdfExportAsOdg) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + { + return; + } + + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, OUString("1").pData); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData); + }); + + loadFromFile(u"two-pages.pdf"); + // save and reload as odg + saveAndReload("draw8"); + + // Check that the graphic in the second page of the document is the second page of the pdf + uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, + uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xDrawPagesSupplier.is()); + uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages()); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(1), uno::UNO_QUERY_THROW); + uno::Reference<drawing::XShape> xImage(xDrawPage->getByIndex(0), uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xImage.is()); + uno::Reference<beans::XPropertySet> xShapeProps(xImage, uno::UNO_QUERY); + uno::Reference<graphic::XGraphic> xGraphic; + CPPUNIT_ASSERT(xShapeProps->getPropertyValue("Graphic") >>= xGraphic); + + Graphic aGraphic(xGraphic); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : -1 + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getPageNumber()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index 54ef1abfebba..3c405d21a0d0 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -1299,7 +1299,8 @@ bool SvXMLImport::IsPackageURL( std::u16string_view rURL ) const return true; } -uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const & rURL) +uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const& rURL, + sal_Int32 nPageNum) { uno::Reference<graphic::XGraphic> xGraphic; @@ -1309,7 +1310,7 @@ uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const & { if (IsPackageURL(rURL)) { - xGraphic = mxGraphicStorageHandler->loadGraphic(rURL); + xGraphic = mxGraphicStorageHandler->loadGraphicAtPage(rURL, nPageNum); } else { diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx index 9d9cb7506b14..92a8e0ed6d98 100644 --- a/xmloff/source/draw/shapeexport.cxx +++ b/xmloff/source/draw/shapeexport.cxx @@ -2498,12 +2498,12 @@ void XMLShapeExport::ImpExportGraphicObjectShape( } { + if (sOutMimeType.isEmpty()) + { + GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType); + } if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012) { - if (sOutMimeType.isEmpty()) - { - GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType); - } if (!sOutMimeType.isEmpty()) { // ODF 1.3 OFFICE-3943 GetExport().AddAttribute( @@ -2514,6 +2514,15 @@ void XMLShapeExport::ImpExportGraphicObjectShape( } } + if (sOutMimeType == "application/pdf") + { + Graphic aGraphic(xGraphic); + sal_Int32 nPage = aGraphic.getPageNumber(); + if (nPage >= 0) + GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PAGE_NUMBER, + OUString::number(nPage)); + } + SvXMLElementExport aElement(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, true, true); // optional office:binary-data diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index dbaefd30b95c..f6bec74799ab 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -2354,10 +2354,10 @@ bool SdXMLCaptionShapeContext::processAttribute( const sax_fastparser::FastAttri SdXMLGraphicObjectShapeContext::SdXMLGraphicObjectShapeContext( - SvXMLImport& rImport, - const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList, - uno::Reference< drawing::XShapes > const & rShapes) -: SdXMLShapeContext( rImport, xAttrList, rShapes, false/*bTemporaryShape*/ ) + SvXMLImport& rImport, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList, + uno::Reference<drawing::XShapes> const& rShapes) + : SdXMLShapeContext(rImport, xAttrList, rShapes, false /*bTemporaryShape*/) + , mnPage(-1) { } @@ -2373,6 +2373,9 @@ bool SdXMLGraphicObjectShapeContext::processAttribute( const sax_fastparser::Fas case XML_ELEMENT(LO_EXT, XML_MIME_TYPE): msMimeType = aIter.toString(); break; + case XML_ELEMENT(LO_EXT, XML_PAGE_NUMBER): + mnPage = aIter.toInt32(); + break; default: return SdXMLShapeContext::processAttribute(aIter); } @@ -2425,7 +2428,8 @@ void SdXMLGraphicObjectShapeContext::startFastElement (sal_Int32 nElement, { if( !maURL.isEmpty() ) { - uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicByURL(maURL); + uno::Reference<graphic::XGraphic> xGraphic + = GetImport().loadGraphicByURL(maURL, mnPage); if (xGraphic.is()) { xPropset->setPropertyValue(u"Graphic"_ustr, uno::Any(xGraphic)); diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx index 9a61f4b594de..6a00cb252e5f 100644 --- a/xmloff/source/draw/ximpshap.hxx +++ b/xmloff/source/draw/ximpshap.hxx @@ -392,6 +392,7 @@ private: OUString maURL; OUString msMimeType; css::uno::Reference < css::io::XOutputStream > mxBase64Stream; + sal_Int32 mnPage; public: OUString const& getMimeType() const { return msMimeType; }