include/sfx2/docfile.hxx | 8 +++ include/vcl/embeddedfontshelper.hxx | 20 +++---- oox/source/ppt/EmbeddedFontListContext.cxx | 1 sfx2/source/doc/docfile.cxx | 16 ++++++ sfx2/source/doc/objmisc.cxx | 2 sfx2/source/doc/sfxbasemodel.cxx | 10 +++ sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx | 2 sw/source/writerfilter/dmapper/FontTable.cxx | 7 +- sw/source/writerfilter/dmapper/FontTable.hxx | 7 ++ vcl/source/gdi/embeddedfontshelper.cxx | 48 +++++++++++++++++-- xmloff/source/core/xmlimp.cxx | 2 11 files changed, 103 insertions(+), 20 deletions(-)
New commits: commit 7dcb33ff91b8d4492f54592ea2240b267f2bf296 Author: Mike Kaganski <[email protected]> AuthorDate: Sun Aug 10 15:29:46 2025 +0500 Commit: Miklos Vajna <[email protected]> CommitDate: Wed Aug 13 12:21:40 2025 +0200 Delay embedded fonts activation until SfxObjectShell::FinishedLoading Embedded fonts may appear several times during document loading. Now, they activate immediately after current element was processed, and a portion of the embedded fonts was collected. The activation may also happen several times during the load process, each time refreshing fonts in all windows, which takes significant time. This change tries to not activate collected fonts in the destructor of EmbeddedFontsHelper, but to send the list to the model. The model accumulates the lists in its medium, and only activates late in the loading process, when all the embedded fonts are collected. Change-Id: Iff188e84e259206541bcc94880d8aead2b72715a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189310 Reviewed-by: Mike Kaganski <[email protected]> Tested-by: Jenkins Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189346 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/include/sfx2/docfile.hxx b/include/sfx2/docfile.hxx index 6ab8d2ce5571..7e5b5aa4b8c6 100644 --- a/include/sfx2/docfile.hxx +++ b/include/sfx2/docfile.hxx @@ -30,6 +30,10 @@ #include <svl/itemset.hxx> #include <tools/link.hxx> #include <tools/stream.hxx> + +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/uno/Sequence.hxx> + #include <mutex> namespace com::sun::star::beans { struct PropertyValue; } @@ -100,6 +104,7 @@ public: DECL_DLLPRIVATE_STATIC_LINK(SfxMedium, ShowReloadEditableDialog, void*, void); bool CheckCanGetLockfile() const; void SetOriginallyReadOnly(bool val); + void AddEmbeddedFonts(const css::uno::Sequence<css::beans::StringPair>& fonts); void AddToCheckEditableWorkerList(); void SetWorkerReloadEvent(ImplSVEvent* pEvent); ImplSVEvent* GetWorkerReloadEvent() const; @@ -202,6 +207,9 @@ public: // independent of later changes via SetOpenMode; used for SID_RELOAD: [[nodiscard]] bool IsOriginallyLoadedReadOnly() const; + // Activates the collected embedded fonts. + void activateEmbeddedFonts(); + [[nodiscard]] bool IsRepairPackage() const; css::uno::Reference< css::io::XInputStream > const & GetInputStream(); diff --git a/include/vcl/embeddedfontshelper.hxx b/include/vcl/embeddedfontshelper.hxx index 1b260fe1aa52..12059c7f07b8 100644 --- a/include/vcl/embeddedfontshelper.hxx +++ b/include/vcl/embeddedfontshelper.hxx @@ -19,6 +19,7 @@ #include <string_view> #include <vector> +namespace com::sun::star::frame { class XModel; } namespace com::sun::star::io { class XInputStream; } namespace com::sun::star::uno { template <typename > class Reference; } @@ -26,14 +27,9 @@ namespace com::sun::star::uno { template <typename > class Reference; } class VCL_DLLPUBLIC EmbeddedFontsHelper { private: + css::uno::Reference<css::frame::XModel> m_xDocumentModel; std::vector<std::pair<OUString, OUString>> m_aAccumulatedFonts; - /** - Adds the accumulated fonts to the list of known fonts. The fonts are used only until application - exit. - */ - void activateFonts(); - public: /// Specification of what kind of operation is allowed when embedding a font enum class FontRights @@ -63,6 +59,12 @@ public: std::vector< unsigned char > const & key, bool eot = false, bool bSubsetted = false); + /** + Adds the passed fonts to the list of known fonts. The fonts are used only until application + exit. + */ + static void activateFonts(std::vector<std::pair<OUString, OUString>>& fonts); + /** Returns if the restrictions specified in the font (if present) allow embedding the font for a particular purpose. @@ -92,10 +94,8 @@ public: */ static bool isCommonFont(std::u16string_view aFontName); - ~EmbeddedFontsHelper() COVERITY_NOEXCEPT_FALSE - { - activateFonts(); - } + EmbeddedFontsHelper(const css::uno::Reference<css::frame::XModel>& xModel); + ~EmbeddedFontsHelper() COVERITY_NOEXCEPT_FALSE; }; #endif diff --git a/oox/source/ppt/EmbeddedFontListContext.cxx b/oox/source/ppt/EmbeddedFontListContext.cxx index de480363a3e3..731048236b10 100644 --- a/oox/source/ppt/EmbeddedFontListContext.cxx +++ b/oox/source/ppt/EmbeddedFontListContext.cxx @@ -24,6 +24,7 @@ EmbeddedFontListContext::EmbeddedFontListContext( FragmentHandler2 const& rParent, bool bEmbedTrueType, css::uno::Reference<css::beans::XPropertySet> const& rxDocSettings) : FragmentHandler2(rParent) + , maEmbeddedFontHelper(getFilter().getModel()) , mbEmbedTrueType(bEmbedTrueType) , mxDocSettings(rxDocSettings) { diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx index 2e7a0b15b4cc..1fce7cb9e7c2 100644 --- a/sfx2/source/doc/docfile.cxx +++ b/sfx2/source/doc/docfile.cxx @@ -125,6 +125,7 @@ #include <openflag.hxx> #include <officecfg/Office/Common.hxx> #include <comphelper/propertysequence.hxx> +#include <vcl/embeddedfontshelper.hxx> #include <vcl/weld.hxx> #include <vcl/svapp.hxx> #include <comphelper/diagnose_ex.hxx> @@ -412,6 +413,9 @@ public: /// if true, xStorage is an inner package and not directly from xStream bool m_bODFWholesomeEncryption = false; + /// font family, file URL + std::vector<std::pair<OUString, OUString>> m_aEmbeddedFontsToActivate; + OUString m_aName; OUString m_aLogicName; OUString m_aLongName; @@ -4001,6 +4005,18 @@ bool SfxMedium::IsOriginallyLoadedReadOnly() const return pImpl->m_bOriginallyLoadedReadOnly; } +void SfxMedium::AddEmbeddedFonts( + const css::uno::Sequence<css::beans::StringPair>& fonts) +{ + for (const auto& [ name, url ] : fonts) + pImpl->m_aEmbeddedFontsToActivate.emplace_back(name, url); +} + +void SfxMedium::activateEmbeddedFonts() +{ + EmbeddedFontsHelper::activateFonts(pImpl->m_aEmbeddedFontsToActivate); +} + bool SfxMedium::SetWritableForUserOnly( const OUString& aURL ) { // UCB does not allow to allow write access only for the user, diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx index a0296194e807..fe51d08b98a2 100644 --- a/sfx2/source/doc/objmisc.cxx +++ b/sfx2/source/doc/objmisc.cxx @@ -1143,6 +1143,8 @@ void SfxObjectShell::FinishedLoading( SfxLoadedFlags nFlags ) pImpl->nFlagsInProgress |= SfxLoadedFlags::MAINDOCUMENT; static_cast<SfxHeaderAttributes_Impl*>(GetHeaderAttributes())->SetAttributes(); + pMedium->activateEmbeddedFonts(); + if ( ( GetModifyPasswordHash() || GetModifyPasswordInfo().hasElements() ) && !IsModifyPasswordEntered() ) SetReadOnly(); diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx index 2d9518530416..7b756faea2c9 100644 --- a/sfx2/source/doc/sfxbasemodel.cxx +++ b/sfx2/source/doc/sfxbasemodel.cxx @@ -44,6 +44,7 @@ #include <com/sun/star/frame/DoubleInitializationException.hpp> #include <com/sun/star/embed/XStorage.hpp> #include <com/sun/star/document/XStorageChangeListener.hpp> +#include <com/sun/star/beans/StringPair.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/XPropertySetInfo.hpp> #include <com/sun/star/container/XIndexContainer.hpp> @@ -1188,6 +1189,15 @@ void SAL_CALL SfxBaseModel::setArgs(const Sequence<beans::PropertyValue>& aArgs) pMedium->GetItemSet().Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, rArg.Value)); ok = true; } + else if (rArg.Name == "EmbeddedFonts") + { + if (uno::Sequence<beans::StringPair> fonts; rArg.Value >>= fonts) + { + pMedium->AddEmbeddedFonts(fonts); + ok = true; + } + } + if (!ok) { throw lang::IllegalArgumentException("Setting property not supported: " + rArg.Name, diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx b/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx index e1a9931ef0fd..96501148f981 100644 --- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx +++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.hxx @@ -868,7 +868,7 @@ public: FontTablePtr const & GetFontTable() { if(!m_pFontTable) - m_pFontTable = new FontTable(m_bReadOnly); + m_pFontTable = new FontTable(m_xTextDocument, m_bReadOnly); return m_pFontTable; } StyleSheetTablePtr const & GetStyleSheetTable() diff --git a/sw/source/writerfilter/dmapper/FontTable.cxx b/sw/source/writerfilter/dmapper/FontTable.cxx index 2c839d3ab1e1..767031b9c13e 100644 --- a/sw/source/writerfilter/dmapper/FontTable.cxx +++ b/sw/source/writerfilter/dmapper/FontTable.cxx @@ -25,15 +25,18 @@ #include <rtl/tencinfo.h> #include <unotools/fontdefs.hxx> +#include <unotxdoc.hxx> + using namespace com::sun::star; namespace writerfilter::dmapper { -FontTable::FontTable(bool bReadOnly) +FontTable::FontTable(const rtl::Reference<SwXTextDocument>& xModel, bool bReadOnly) : LoggedProperties("FontTable") , LoggedTable("FontTable") , LoggedStream("FontTable") +, m_xModel(xModel) , m_bReadOnly(bReadOnly) { } @@ -253,7 +256,7 @@ void FontTable::addEmbeddedFont(const css::uno::Reference<css::io::XInputStream> bool bSubsetted) { if (!m_xEmbeddedFontHelper) - m_xEmbeddedFontHelper.reset(new EmbeddedFontsHelper); + m_xEmbeddedFontHelper.reset(new EmbeddedFontsHelper(m_xModel)); m_xEmbeddedFontHelper->addEmbeddedFont(stream, fontName, extra, key, /*eot=*/false, bSubsetted); } diff --git a/sw/source/writerfilter/dmapper/FontTable.hxx b/sw/source/writerfilter/dmapper/FontTable.hxx index 7f9c545c9f73..56b949fd04c1 100644 --- a/sw/source/writerfilter/dmapper/FontTable.hxx +++ b/sw/source/writerfilter/dmapper/FontTable.hxx @@ -23,10 +23,14 @@ #include <vector> #include "LoggedResources.hxx" #include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/frame/XModel2.hpp> #include <com/sun/star/awt/FontFamily.hpp> #include <vcl/embeddedfontshelper.hxx> #include <o3tl/deleter.hxx> +namespace rtl { template<class reference_type> class Reference; } +class SwXTextDocument; + namespace writerfilter::dmapper { @@ -46,13 +50,14 @@ struct FontEntry : public virtual SvRefBase class FontTable : public LoggedProperties, public LoggedTable /*,public BinaryObj*/, public LoggedStream { + css::uno::Reference<css::frame::XModel2> m_xModel; std::unique_ptr<EmbeddedFontsHelper, o3tl::default_delete<EmbeddedFontsHelper>> m_xEmbeddedFontHelper; std::vector< FontEntry::Pointer_t > m_aFontEntries; FontEntry::Pointer_t m_pCurrentEntry; bool m_bReadOnly; public: - FontTable(bool bReadOnly); + FontTable(const rtl::Reference<SwXTextDocument>& xModel, bool bReadOnly); virtual ~FontTable() override; sal_uInt32 size(); diff --git a/vcl/source/gdi/embeddedfontshelper.cxx b/vcl/source/gdi/embeddedfontshelper.cxx index 15738c4fb351..cbbf9195289d 100644 --- a/vcl/source/gdi/embeddedfontshelper.cxx +++ b/vcl/source/gdi/embeddedfontshelper.cxx @@ -23,6 +23,8 @@ #include <vcl/svapp.hxx> #include <vcl/embeddedfontshelper.hxx> #include <com/sun/star/io/XInputStream.hpp> +#include <comphelper/diagnose_ex.hxx> +#include <comphelper/propertyvalue.hxx> #include <comphelper/storagehelper.hxx> #include <font/PhysicalFontFaceCollection.hxx> @@ -30,6 +32,9 @@ #include <salgdi.hxx> #include <sft.hxx> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/frame/XModel2.hpp> + #if ENABLE_EOT extern "C" { @@ -147,6 +152,39 @@ bool writeFontBytesToFile(const std::vector<char>& bytes, std::u16string_view na } } +EmbeddedFontsHelper::EmbeddedFontsHelper(const uno::Reference<frame::XModel>& xModel) + : m_xDocumentModel(xModel) +{ +} + +EmbeddedFontsHelper::~EmbeddedFontsHelper() COVERITY_NOEXCEPT_FALSE +{ + if (m_aAccumulatedFonts.empty()) + return; + + if (auto xModel2 = m_xDocumentModel.query<frame::XModel2>()) + { + // Send embedded fonts list into the document's media descriptor. + // This helps to decide if the document is allowed to switch to edit mode. + try + { + uno::Sequence<beans::StringPair> fonts(m_aAccumulatedFonts.size()); + std::transform(m_aAccumulatedFonts.begin(), m_aAccumulatedFonts.end(), fonts.getArray(), + [](const auto& el) { return beans::StringPair(el.first, el.second); }); + xModel2->setArgs({ comphelper::makePropertyValue(u"EmbeddedFonts"_ustr, fonts) }); + // The following will not get executed, it setArgs throws + return; + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("xmloff.core"); + } + } + + // Failed to transfer the read-only fonts to the document. Activate them here. + activateFonts(m_aAccumulatedFonts); +} + void EmbeddedFontsHelper::clearTemporaryFontFiles() { OUString path = GetEmbeddedFontsRoot(); @@ -264,15 +302,15 @@ namespace }; } -void EmbeddedFontsHelper::activateFonts() +void EmbeddedFontsHelper::activateFonts(std::vector<std::pair<OUString, OUString>>& fonts) { - if (m_aAccumulatedFonts.empty()) + if (fonts.empty()) return; UpdateFontsGuard aUpdateFontsGuard; OutputDevice *pDevice = Application::GetDefaultDevice(); - for (const auto& rEntry : m_aAccumulatedFonts) - pDevice->AddTempDevFont(rEntry.second, rEntry.first); - m_aAccumulatedFonts.clear(); + for (const auto& [ fontName, fileUrl ] : fonts) + pDevice->AddTempDevFont(fileUrl, fontName); + fonts.clear(); } // Check if it's (legally) allowed to embed the font file into a document diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx index 886b8f10d6df..e5b59f57471b 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -496,7 +496,7 @@ bool SvXMLImport::addEmbeddedFont(const css::uno::Reference< css::io::XInputStre std::vector<unsigned char> const & key, bool eot) { if (!mxEmbeddedFontHelper) - mxEmbeddedFontHelper.reset(new EmbeddedFontsHelper); + mxEmbeddedFontHelper.reset(new EmbeddedFontsHelper(mxModel)); return mxEmbeddedFontHelper->addEmbeddedFont(stream, fontName, extra, key, eot); }
