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 badc9c68dcbb12b358a81999618c57befcb411ed Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Aug 10 15:29:46 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Aug 10 15:23:12 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 <mike.kagan...@collabora.com> Tested-by: Jenkins 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 87d23df72e40..a392e091cc19 100644 --- a/sfx2/source/doc/docfile.cxx +++ b/sfx2/source/doc/docfile.cxx @@ -126,6 +126,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> @@ -413,6 +414,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; @@ -3998,6 +4002,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 9dbf71c0948b..dd52481d2687 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 603757f882e0..671ddf6c2180 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> @@ -1199,6 +1200,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 f578e3f0a229..fd3c170b1cb1 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 a4d4f88c757e..3597207b1b35 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" { @@ -151,6 +156,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() { const OUString& path = GetEmbeddedFontsRoot(); @@ -268,15 +306,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 368b54ae792f..a4704f9cdcd2 100644 --- a/xmloff/source/core/xmlimp.cxx +++ b/xmloff/source/core/xmlimp.cxx @@ -504,7 +504,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); }