desktop/source/lib/init.cxx | 2 include/svl/cryptosign.hxx | 2 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 postprocess/CustomTarget_registry.mk | 4 schema/libreoffice/OpenDocument-v1.4+libreoffice-schema.rng | 9 ++ sfx2/source/control/dispatch.cxx | 1 sfx2/source/sidebar/ResourceManager.cxx | 6 - svx/source/xml/xmlgrhlp.cxx | 49 ++++++++++-- sw/inc/init.hxx | 5 - sw/qa/core/header_footer/HeaderFooterTest.cxx | 5 + sw/qa/extras/rtfexport/rtfexport8.cxx | 12 ++ sw/source/filter/basflt/fltini.cxx | 24 ++--- sw/source/uibase/app/swdll.cxx | 3 sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx | 2 sw/source/writerfilter/dmapper/PropertyMap.cxx | 39 +++++---- 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/ProgressBarHelper.cxx | 4 xmloff/source/core/SettingsExportHelper.cxx | 2 xmloff/source/core/xmlimp.cxx | 5 - xmloff/source/draw/shapeexport.cxx | 17 +++- xmloff/source/draw/ximpshap.cxx | 14 ++- xmloff/source/draw/ximpshap.hxx | 1 33 files changed, 244 insertions(+), 90 deletions(-)
New commits: commit 47176d05f01c714af1e3d010da1cb59016dd4a75 Author: Patrick Luby <guibmac...@gmail.com> AuthorDate: Tue Nov 12 10:07:29 2024 -0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 13:08:13 2025 +0100 Fix iOS build failure when building with Xcode 16.1 on macOS Sequoia Change-Id: I21c0ff32298bdc1309b2d0dd6152e1f5f43746e4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176485 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> Reviewed-by: Patrick Luby <guibomac...@gmail.com> diff --git a/include/svl/cryptosign.hxx b/include/svl/cryptosign.hxx index 154292b5f3ce..8c8e48f0da54 100644 --- a/include/svl/cryptosign.hxx +++ b/include/svl/cryptosign.hxx @@ -86,7 +86,7 @@ public: private: /// The certificate to use for signing. - svl::crypto::SigningContext& m_rSigningContext; + [[maybe_unused]] svl::crypto::SigningContext& m_rSigningContext; /// Data blocks (pointer-size pairs). std::vector<std::pair<const void*, sal_Int32>> m_dataBlocks; commit 8f27023ea81490eeef6163f1aef93f5643adefb8 Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Thu Jan 16 20:25:22 2025 -0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 12:20:38 2025 +0100 tdf#164748 writerfilter: fix missing even/odd header properties Lots of header/footer page style properties are ignored if the header/footer is not first enabled. So copying propertyList MUST follow completeCopyHeaderFooter() [which is where all those settings are turned on]. However, copying properties AFTER turning on the header/footer was Exception'ing when trying to copy BottomMarginComplexColor as void(). So ignore any property-copy errors, and then everything should work in theory... ...and it seems to. make CppunitTest_sw_core_header_footer \ CPPUNIT_TEST_NAME=testBnc519228OddBreaks make CppunitTest_sw_rtfexport8 \ CPPUNIT_TEST_NAME=testTdf160976_headerFooter Change-Id: Iecf0a070e77525c04b44c4fc38efa0f9d558eca5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180417 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/sw/qa/core/header_footer/HeaderFooterTest.cxx b/sw/qa/core/header_footer/HeaderFooterTest.cxx index af4e388dff2f..f277a0ed77aa 100644 --- a/sw/qa/core/header_footer/HeaderFooterTest.cxx +++ b/sw/qa/core/header_footer/HeaderFooterTest.cxx @@ -643,6 +643,8 @@ CPPUNIT_TEST_FIXTURE(HeaderFooterTest, testFirstPageFooterEnabled) CPPUNIT_TEST_FIXTURE(HeaderFooterTest, testBnc519228OddBreaks) { auto verify = [this]() { + CPPUNIT_ASSERT_EQUAL(5, getPages()); // logical pages - "blank page" 4 usually not displayed + // Check that all the normal styles are not set as right-only, those should be only those used after odd page breaks. auto xStyles = getStyles(u"PageStyles"_ustr); uno::Reference<beans::XPropertySet> xStyle; @@ -696,6 +698,9 @@ CPPUNIT_TEST_FIXTURE(HeaderFooterTest, testBnc519228OddBreaks) CPPUNIT_ASSERT_EQUAL(getProperty<sal_Int32>(page1Style, u"TopMargin"_ustr), getProperty<sal_Int32>(page2Style, u"TopMargin"_ustr)); + //tdf164748 + CPPUNIT_ASSERT_EQUAL(getProperty<bool>(page1Style, u"HeaderDynamicSpacing"_ustr), + getProperty<bool>(page2Style, u"HeaderDynamicSpacing"_ustr)); } // Page 5 diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx b/sw/qa/extras/rtfexport/rtfexport8.cxx index 7184b7cc5b89..e8e607c59126 100644 --- a/sw/qa/extras/rtfexport/rtfexport8.cxx +++ b/sw/qa/extras/rtfexport/rtfexport8.cxx @@ -431,6 +431,18 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf160976_headerFooter) verify(); saveAndReload(mpFilter); verify(/*IsExported*/ true); + + //tdf#164748: export must have the all same footer settings as the first page + auto xStyles = getStyles(u"PageStyles"_ustr); + auto xPara = getParagraph(2, "2"); + OUString page2StyleName = getProperty<OUString>(xPara, u"PageDescName"_ustr); + uno::Reference<beans::XPropertySet> page2Style; + page2Style.set(xStyles->getByName(page2StyleName), uno::UNO_QUERY); + CPPUNIT_ASSERT(getProperty<bool>(page2Style, u"FooterDynamicSpacing"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(915), + getProperty<sal_Int32>(page2Style, u"FooterBodyDistance"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1016), getProperty<sal_Int32>(page2Style, u"FooterHeight"_ustr)); + // note: an unexpected header surfaces on page 3. } diff --git a/sw/source/writerfilter/dmapper/PropertyMap.cxx b/sw/source/writerfilter/dmapper/PropertyMap.cxx index ce373b092890..efd038964444 100644 --- a/sw/source/writerfilter/dmapper/PropertyMap.cxx +++ b/sw/source/writerfilter/dmapper/PropertyMap.cxx @@ -1478,11 +1478,22 @@ void SectionPropertyMap::CreateEvenOddPageStyleCopy(DomainMapper_Impl& rDM_Impl, { OUString evenOddStyleName = rDM_Impl.GetUnusedPageStyleName(); rtl::Reference<SwXPageStyle> evenOddStyle = rDM_Impl.GetTextDocument()->createPageStyle(); - // Unfortunately using setParent() does not work for page styles, so make a deep copy of the page style. + rDM_Impl.GetPageStyles()->insertStyleByName(evenOddStyleName, evenOddStyle); + rtl::Reference<SwXPageStyle> pageProperties(m_aPageStyle); uno::Reference<beans::XPropertySetInfo> pagePropertiesInfo(pageProperties->getPropertySetInfo()); const uno::Sequence<beans::Property> propertyList(pagePropertiesInfo->getProperties()); + if (rDM_Impl.IsNewDoc()) + { + bool const bEvenAndOdd(rDM_Impl.GetSettingsTable()->GetEvenAndOddHeaders()); + completeCopyHeaderFooter(pageProperties, evenOddStyle, + !rDM_Impl.SeenHeaderFooter(PagePartType::Header, PageType::RIGHT) + && (!bEvenAndOdd || !rDM_Impl.SeenHeaderFooter(PagePartType::Header, PageType::LEFT)), + !rDM_Impl.SeenHeaderFooter(PagePartType::Footer, PageType::RIGHT) + && (!bEvenAndOdd || !rDM_Impl.SeenHeaderFooter(PagePartType::Footer, PageType::LEFT))); + } + // Ignore write-only properties. static constexpr auto staticDenylist = frozen::make_unordered_set<std::u16string_view>({ u"FooterBackGraphicURL", u"BackGraphicURL", u"HeaderBackGraphicURL", @@ -1492,6 +1503,7 @@ void SectionPropertyMap::CreateEvenOddPageStyleCopy(DomainMapper_Impl& rDM_Impl, u"FooterText", u"FooterTextLeft", u"FooterTextFirst" }); + // Unfortunately page styles can't inherit from a parent, so make a deep copy of the page style. bool isMirrorMargins = PageBreakType::Even == eBreakType && rDM_Impl.GetSettingsTable()->GetMirrorMarginSettings(); for (const auto& rProperty : propertyList) { @@ -1507,26 +1519,21 @@ void SectionPropertyMap::CreateEvenOddPageStyleCopy(DomainMapper_Impl& rDM_Impl, else if (rProperty.Name == u"RightMargin"_ustr) sSetName = u"LeftMargin"_ustr; } - evenOddStyle->setPropertyValue( - sSetName, - pageProperties->getPropertyValue(rProperty.Name)); + try + { + evenOddStyle->setPropertyValue( + sSetName, + pageProperties->getPropertyValue(rProperty.Name)); + } + catch (uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("writerfilter", "failed to copy page style property"); + } } } } evenOddStyle->setPropertyValue(u"FollowStyle"_ustr, uno::Any(m_sPageStyleName)); - rDM_Impl.GetPageStyles()->insertStyleByName(evenOddStyleName, evenOddStyle); - - if (rDM_Impl.IsNewDoc()) - { - bool const bEvenAndOdd(rDM_Impl.GetSettingsTable()->GetEvenAndOddHeaders()); - completeCopyHeaderFooter(pageProperties, evenOddStyle, - !rDM_Impl.SeenHeaderFooter(PagePartType::Header, PageType::RIGHT) - && (!bEvenAndOdd || !rDM_Impl.SeenHeaderFooter(PagePartType::Header, PageType::LEFT)), - !rDM_Impl.SeenHeaderFooter(PagePartType::Footer, PageType::RIGHT) - && (!bEvenAndOdd || !rDM_Impl.SeenHeaderFooter(PagePartType::Footer, PageType::LEFT))); - } - if (eBreakType == PageBreakType::Even) evenOddStyle->setPropertyValue(getPropertyName(PROP_PAGE_STYLE_LAYOUT), uno::Any(style::PageStyleLayout_LEFT)); else if (eBreakType == PageBreakType::Odd) commit 5179087be6cff5afdf6091d44538a2dda50a4f51 Author: Aron Budea <aron.bu...@collabora.com> AuthorDate: Sun Jan 19 03:23:51 2025 +1030 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 12:19:30 2025 +0100 LOK: Use OOXML 2010+ format Change-Id: Ic2deac5602293cfcd1a1a73774dab94b2c4c970a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180458 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 6f7e5f6c26a212c3fdbff3b97522d05a5ab896cb) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180500 Reviewed-by: Aron Budea <aron.bu...@collabora.com> Tested-by: Jenkins diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 06ea11391d80..200bf411996c 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -322,7 +322,7 @@ constexpr ExtensionMap aWriterExtensionMap[] = { { "doc", u"MS Word 97"_ustr }, { "docm", u"MS Word 2007 XML VBA"_ustr }, - { "docx", u"MS Word 2007 XML"_ustr }, + { "docx", u"Office Open XML Text"_ustr }, { "fodt", u"OpenDocument Text Flat XML"_ustr }, { "html", u"HTML (StarWriter)"_ustr }, { "odt", u"writer8"_ustr }, commit 013092b83a91a485896a615b03cd47d2722c1846 Author: Aron Budea <aron.bu...@collabora.com> AuthorDate: Mon Jan 6 18:20:34 2025 +1030 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 12:18:29 2025 +0100 Slightly more informative logging Change-Id: Ia474a208d5a562e424df76ff389cfcc4e3f2b1fc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179817 Tested-by: Jenkins Reviewed-by: Aron Budea <aron.bu...@collabora.com> (cherry picked from commit 899d87a844c2aa2990df4a9268008960d8489379) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180151 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Andras Timar <andras.ti...@collabora.com> diff --git a/sfx2/source/sidebar/ResourceManager.cxx b/sfx2/source/sidebar/ResourceManager.cxx index cf333c1b0a8f..f4066c0eb972 100644 --- a/sfx2/source/sidebar/ResourceManager.cxx +++ b/sfx2/source/sidebar/ResourceManager.cxx @@ -518,7 +518,7 @@ void ResourceManager::ReadContextList ( } else { - OSL_FAIL("expecting three or four values per ContextList entry, separated by comma"); + SAL_WARN("sfx.sidebar", "expecting three or four values per ContextList entry, separated by comma, entries: " << aValues); continue; } } @@ -526,7 +526,7 @@ void ResourceManager::ReadContextList ( const OUString sContextName(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex))); if (nCharacterIndex < 0) { - OSL_FAIL("expecting three or four values per ContextList entry, separated by comma"); + SAL_WARN("sfx.sidebar", "expecting three or four values per ContextList entry, separated by comma"); continue; } @@ -617,7 +617,7 @@ void ResourceManager::ReadContextList ( bIsInitiallyVisible = false; else { - OSL_FAIL("unrecognized state"); + SAL_WARN("sfx.sidebar", "unrecognized state"); continue; } diff --git a/xmloff/source/core/ProgressBarHelper.cxx b/xmloff/source/core/ProgressBarHelper.cxx index 3ff70fb0434d..9f2ddcd585c3 100644 --- a/xmloff/source/core/ProgressBarHelper.cxx +++ b/xmloff/source/core/ProgressBarHelper.cxx @@ -20,7 +20,7 @@ #include <utility> #include <xmloff/ProgressBarHelper.hxx> -#include <osl/diagnose.h> +#include <sal/log.hxx> using namespace ::com::sun::star; @@ -99,7 +99,7 @@ void ProgressBarHelper::SetValue(sal_Int32 nTempValue) #ifdef DBG_UTIL else if (!m_bFailure) { - OSL_FAIL("tried to set a wrong value on the progressbar"); + SAL_WARN("xmloff", "tried to set a wrong value (" << nTempValue << ") on the progressbar"); m_bFailure = true; } #endif diff --git a/xmloff/source/core/SettingsExportHelper.cxx b/xmloff/source/core/SettingsExportHelper.cxx index 3f6f87fa1bbb..db6f29a1512b 100644 --- a/xmloff/source/core/SettingsExportHelper.cxx +++ b/xmloff/source/core/SettingsExportHelper.cxx @@ -168,7 +168,7 @@ void XMLSettingsExportHelper::CallTypeFunction(const uno::Any& rAny, exportSymbolDescriptors(aProps, rName); } else { - OSL_FAIL("this type is not implemented now"); + SAL_WARN("xmloff", "this type (" << aType.getTypeName() << ") is not implemented now"); } } break; commit 1ebef218cc66e19db2c0fe0f2b3237fd844a3c07 Author: Justin Luth <justin.l...@collabora.com> AuthorDate: Mon Dec 16 14:02:18 2024 -0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 12:15:29 2025 +0100 tdf#164075 rtfimport: ignore assert developed for DOCX fixing I don't exactly remember why I put the assert there, but it sounds reasonable to expect that if the paragraph defined the numbering that it should also have numbering rule content, and if it doesn't, then it is worth investigating why. Investing anything related to RTF is never worthwhile. Change-Id: I6525d0a40d9535f1888056a610576085941605a3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178607 Reviewed-by: Justin Luth <jl...@mail.com> Tested-by: Jenkins diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx index efe48d107dfe..24712f454782 100644 --- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx +++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx @@ -2653,7 +2653,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con return rValue.Name == "NumberingRules"; }); - assert( isNumberingViaRule == (itNumberingRules != aProperties.end()) ); + assert(isNumberingViaRule == (itNumberingRules != aProperties.end()) || IsRTFImport()); isNumberingViaRule = (itNumberingRules != aProperties.end()); if (m_StreamStateStack.top().xPreviousParagraph.is() && (isNumberingViaRule || isNumberingViaStyle)) commit ec00dab0d3bfdca7a5438ed36f77802f09f2aa1f Author: Gökay Şatır <gokaysa...@collabora.com> AuthorDate: Tue Jan 7 12:48:00 2025 +0300 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 12:14:34 2025 +0100 Make sure that certain accelerator files are included for LOK case. Issue: Accelerators-unxwnt file is omitted when window system is different than X11. This causes LOK to miss the shortcuts which has "install:module="unxwnt"" signature. This commit adds the required file in linux case. Change-Id: I4a8425d17a5d95b03a176153506f29a3f393c173 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181204 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/postprocess/CustomTarget_registry.mk b/postprocess/CustomTarget_registry.mk index d7c7555dc7be..7b5e52edcc12 100644 --- a/postprocess/CustomTarget_registry.mk +++ b/postprocess/CustomTarget_registry.mk @@ -293,6 +293,10 @@ postprocess_FILES_main += \ $(postprocess_MOD)/org/openoffice/VCL-unixdesktop.xcu # Inet-unixdesktop.xcu must come after Inet.xcu # VCL-unixdesktop.xcu must come after VCL.xcu +else ifeq (LINUX,$(OS)) +postprocess_FILES_main += \ + $(postprocess_MOD)/org/openoffice/Office/Accelerators-unxwnt.xcu + # This condition is for LOK case. When the windowing system is not X11, above condition is not met. So we add the required files here. else ifeq (WNT,$(OS)) postprocess_FILES_main += \ $(postprocess_MOD)/org/openoffice/Inet-wnt.xcu \ commit 740f820b913c8c116638c5b3b5c308d096545a73 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Jan 21 20:14:01 2025 +0000 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 12:12:22 2025 +0100 add loading libmswordlo.so to lok_preload_hook similar to libscfiltlo.so in calc's lok_preload_hook so the module is loaded before any chroot might leave the original libs unavailable to find. Change-Id: I94e88dcd488ba15dc7781078796930e10f32b45c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180560 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sw/inc/init.hxx b/sw/inc/init.hxx index 438be221de6c..5c6e358c0a01 100644 --- a/sw/inc/init.hxx +++ b/sw/inc/init.hxx @@ -48,11 +48,8 @@ public: ~Filters(); #ifndef DISABLE_DYNLOADING - oslGenericFunction GetMswordLibSymbol( const char *pSymbol ); + static oslGenericFunction GetMswordLibSymbol( const char *pSymbol ); #endif - -private: - osl::Module msword_; }; } diff --git a/sw/source/filter/basflt/fltini.cxx b/sw/source/filter/basflt/fltini.cxx index 6e37bfb1ebb3..744ec4a1379d 100644 --- a/sw/source/filter/basflt/fltini.cxx +++ b/sw/source/filter/basflt/fltini.cxx @@ -121,22 +121,22 @@ Filters::~Filters() rEntry.pReader = nullptr; } } - msword_.release(); } #ifndef DISABLE_DYNLOADING oslGenericFunction Filters::GetMswordLibSymbol( const char *pSymbol ) { - if (!msword_.is()) + static ::osl::Module aModule; + if (!aModule.is()) { OUString url(u"$LO_LIB_DIR/" SVLIBRARY("msword") ""_ustr); rtl::Bootstrap::expandMacros(url); - bool ok = msword_.load( url, SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY ); + bool ok = aModule.load( url, SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY ); SAL_WARN_IF(!ok, "sw", "failed to load msword library"); } - if (msword_.is()) - return msword_.getFunctionSymbol( OUString::createFromAscii( pSymbol ) ); + if (aModule.is()) + return aModule.getFunctionSymbol( OUString::createFromAscii( pSymbol ) ); return nullptr; } @@ -627,7 +627,7 @@ Reader* GetRTFReader() { #ifndef DISABLE_DYNLOADING - FnGetReader pFunction = reinterpret_cast<FnGetReader>( SwGlobals::getFilters().GetMswordLibSymbol( "ImportRTF" ) ); + FnGetReader pFunction = reinterpret_cast<FnGetReader>( sw::Filters::GetMswordLibSymbol( "ImportRTF" ) ); if ( pFunction ) return (*pFunction)(); @@ -642,7 +642,7 @@ Reader* GetRTFReader() void GetRTFWriter( std::u16string_view rFltName, const OUString& rBaseURL, WriterRef& xRet ) { #ifndef DISABLE_DYNLOADING - FnGetWriter pFunction = reinterpret_cast<FnGetWriter>( SwGlobals::getFilters().GetMswordLibSymbol( "ExportRTF" ) ); + FnGetWriter pFunction = reinterpret_cast<FnGetWriter>( sw::Filters::GetMswordLibSymbol( "ExportRTF" ) ); if ( pFunction ) (*pFunction)( rFltName, rBaseURL, xRet ); @@ -656,7 +656,7 @@ void GetRTFWriter( std::u16string_view rFltName, const OUString& rBaseURL, Write Reader* GetWW8Reader() { #ifndef DISABLE_DYNLOADING - FnGetReader pFunction = reinterpret_cast<FnGetReader>( SwGlobals::getFilters().GetMswordLibSymbol( "ImportDOC" ) ); + FnGetReader pFunction = reinterpret_cast<FnGetReader>( sw::Filters::GetMswordLibSymbol( "ImportDOC" ) ); if ( pFunction ) return (*pFunction)(); @@ -670,7 +670,7 @@ Reader* GetWW8Reader() void GetWW8Writer( std::u16string_view rFltName, const OUString& rBaseURL, WriterRef& xRet ) { #ifndef DISABLE_DYNLOADING - FnGetWriter pFunction = reinterpret_cast<FnGetWriter>( SwGlobals::getFilters().GetMswordLibSymbol( "ExportDOC" ) ); + FnGetWriter pFunction = reinterpret_cast<FnGetWriter>( sw::Filters::GetMswordLibSymbol( "ExportDOC" ) ); if ( pFunction ) (*pFunction)( rFltName, rBaseURL, xRet ); @@ -684,7 +684,7 @@ void GetWW8Writer( std::u16string_view rFltName, const OUString& rBaseURL, Write Reader* GetDOCXReader() { #ifndef DISABLE_DYNLOADING - FnGetReader pFunction = reinterpret_cast<FnGetReader>( SwGlobals::getFilters().GetMswordLibSymbol( "ImportDOCX" ) ); + FnGetReader pFunction = reinterpret_cast<FnGetReader>( sw::Filters::GetMswordLibSymbol( "ImportDOCX" ) ); if ( pFunction ) return (*pFunction)(); @@ -701,7 +701,7 @@ typedef sal_uInt32 ( *GetSaveWarning )( SfxObjectShell& ); ErrCode SaveOrDelMSVBAStorage( SfxObjectShell& rDoc, SotStorage& rStor, bool bSaveInto, const OUString& rStorageName ) { #ifndef DISABLE_DYNLOADING - SaveOrDel pFunction = reinterpret_cast<SaveOrDel>( SwGlobals::getFilters().GetMswordLibSymbol( "SaveOrDelMSVBAStorage_ww8" ) ); + SaveOrDel pFunction = reinterpret_cast<SaveOrDel>( sw::Filters::GetMswordLibSymbol( "SaveOrDelMSVBAStorage_ww8" ) ); if( pFunction ) return ErrCode(pFunction( rDoc, rStor, bSaveInto, rStorageName )); return ERRCODE_NONE; @@ -713,7 +713,7 @@ ErrCode SaveOrDelMSVBAStorage( SfxObjectShell& rDoc, SotStorage& rStor, bool bSa ErrCode GetSaveWarningOfMSVBAStorage( SfxObjectShell &rDocS ) { #ifndef DISABLE_DYNLOADING - GetSaveWarning pFunction = reinterpret_cast<GetSaveWarning>( SwGlobals::getFilters().GetMswordLibSymbol( "GetSaveWarningOfMSVBAStorage_ww8" ) ); + GetSaveWarning pFunction = reinterpret_cast<GetSaveWarning>( sw::Filters::GetMswordLibSymbol( "GetSaveWarningOfMSVBAStorage_ww8" ) ); if( pFunction ) return ErrCode(pFunction( rDocS )); return ERRCODE_NONE; diff --git a/sw/source/uibase/app/swdll.cxx b/sw/source/uibase/app/swdll.cxx index a0d0d35773dd..274b0e50c319 100644 --- a/sw/source/uibase/app/swdll.cxx +++ b/sw/source/uibase/app/swdll.cxx @@ -176,6 +176,9 @@ sw::Filters & SwDLL::getFilters() extern "C" SAL_DLLPUBLIC_EXPORT void lok_preload_hook() { + // msword (any symbol will do) + sw::Filters::GetMswordLibSymbol("ImportDOC"); + // swui SwAbstractDialogFactory::Create(); } commit e724004aac8026837dd8381bf61523253d03627b Author: Jaume Pujantell <jaume.pujant...@collabora.com> AuthorDate: Thu Jan 30 12:11:39 2025 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 11:56:04 2025 +0100 lok: allow save on comment only mode Allow execution of .uno:Save command on comment only mode for all types of files, not only pdf. Change-Id: I35387d93d00d709d209d3ed1ba2d315bd20b67d5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180940 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit adcfa0902b8641a50b11c9fb528bb971993d5f12) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181026 Reviewed-by: Jaume Pujantell <jaume.pujant...@collabora.com> Tested-by: Jenkins diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx index cb0f26e3c4b6..1959b5e81efa 100644 --- a/sfx2/source/control/dispatch.cxx +++ b/sfx2/source/control/dispatch.cxx @@ -1543,6 +1543,7 @@ bool SfxDispatcher::IsCommandAllowedInLokReadOnlyViewMode (const OUString & comm u".uno:DeleteAnnotation"_ustr, u".uno:EditAnnotation"_ustr, u".uno:PromoteComment"_ustr, + u".uno:Save"_ustr, }; if (std::find(std::begin(allowedList), std::end(allowedList), commandName) != std::end(allowedList)) commit a12bd4fedfc3f269f1dbb5fea36b607facd1261d Author: Jaume Pujantell <jaume.pujant...@collabora.com> AuthorDate: Tue Jan 28 10:13:11 2025 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Feb 9 11:51:38 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 3c09f949ba26..f72f65ba9d90 100644 --- a/include/vcl/graphicfilter.hxx +++ b/include/vcl/graphicfilter.hxx @@ -273,10 +273,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. /// @@ -290,7 +291,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(); @@ -318,7 +320,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 72508a548293..4a78aa68b156 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -37,10 +37,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 82eddedd6e45..89108377312a 100644 --- a/include/xmloff/xmlimp.hxx +++ b/include/xmloff/xmlimp.hxx @@ -410,7 +410,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; }