diff --git a/include/sfx2/docfile.hxx b/include/sfx2/docfile.hxx index 7e5b5aa4b8c6..e15983b65a6c 100644 --- a/include/sfx2/docfile.hxx +++ b/include/sfx2/docfile.hxx @@ -31,12 +31,12 @@ #include #include -#include #include #include namespace com::sun::star::beans { struct PropertyValue; } +namespace com::sun::star::beans { struct StringPair; } namespace com::sun::star::embed { class XStorage; } namespace com::sun::star::graphic { class XGraphic; } namespace com::sun::star::io { class XInputStream; } @@ -105,6 +105,8 @@ public: bool CheckCanGetLockfile() const; void SetOriginallyReadOnly(bool val); void AddEmbeddedFonts(const css::uno::Sequence& fonts); + // Transfers the embedded font list to another medium (passing ownership) + void TransferEmbeddedFontsTo(SfxMedium& target); void AddToCheckEditableWorkerList(); void SetWorkerReloadEvent(ImplSVEvent* pEvent); ImplSVEvent* GetWorkerReloadEvent() const; @@ -322,6 +324,7 @@ private: bool bIsLoading, bool bOwnLock, bool bHandleSysLocked); enum class MessageDlg { LockFileIgnore, LockFileCorrupt }; bool ShowLockFileProblemDialog(MessageDlg nWhichDlg); + void ReleaseEmbeddedFonts(); }; #endif diff --git a/include/vcl/embeddedfontshelper.hxx b/include/vcl/embeddedfontshelper.hxx index 12059c7f07b8..fa4129976040 100644 --- a/include/vcl/embeddedfontshelper.hxx +++ b/include/vcl/embeddedfontshelper.hxx @@ -94,6 +94,8 @@ public: */ static bool isCommonFont(std::u16string_view aFontName); + static void releaseFonts(const std::vector>& fonts); + EmbeddedFontsHelper(const css::uno::Reference& xModel); ~EmbeddedFontsHelper() COVERITY_NOEXCEPT_FALSE; }; diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index d136e259cddd..4e75a66e3c9d 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1131,6 +1131,7 @@ public: bool IsFontAvailable( std::u16string_view rFontName ) const; bool AddTempDevFont( const OUString& rFileURL, const OUString& rFontName ); + bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ); void RefreshFontData( const bool bNewFontLists ); FontMetric GetFontMetric() const; diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx index a392e091cc19..164c064cdaf8 100644 --- a/sfx2/source/doc/docfile.cxx +++ b/sfx2/source/doc/docfile.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -415,6 +416,7 @@ public: bool m_bODFWholesomeEncryption = false; /// font family, file URL + std::vector> m_aEmbeddedFonts; std::vector> m_aEmbeddedFontsToActivate; OUString m_aName; @@ -3736,6 +3738,8 @@ SfxMedium::~SfxMedium() Close(/*bInDestruction*/true); + ReleaseEmbeddedFonts(); + if( !pImpl->bIsTemp || pImpl->m_aName.isEmpty() ) return; @@ -3752,6 +3756,15 @@ SfxMedium::~SfxMedium() } } +void SfxMedium::ReleaseEmbeddedFonts() +{ + std::vector> toRelease(std::move(pImpl->m_aEmbeddedFonts)); + toRelease.insert(toRelease.end(), pImpl->m_aEmbeddedFontsToActivate.begin(), + pImpl->m_aEmbeddedFontsToActivate.end()); + pImpl->m_aEmbeddedFontsToActivate.clear(); + EmbeddedFontsHelper::releaseFonts(toRelease); +} + const OUString& SfxMedium::GetName() const { return pImpl->m_aLogicName; @@ -4002,6 +4015,18 @@ bool SfxMedium::IsOriginallyLoadedReadOnly() const return pImpl->m_bOriginallyLoadedReadOnly; } +void SfxMedium::TransferEmbeddedFontsTo(SfxMedium& target) +{ + target.pImpl->m_aEmbeddedFonts.insert(target.pImpl->m_aEmbeddedFonts.end(), + pImpl->m_aEmbeddedFonts.begin(), + pImpl->m_aEmbeddedFonts.end()); + pImpl->m_aEmbeddedFonts.clear(); + target.pImpl->m_aEmbeddedFontsToActivate.insert(target.pImpl->m_aEmbeddedFontsToActivate.end(), + pImpl->m_aEmbeddedFontsToActivate.begin(), + pImpl->m_aEmbeddedFontsToActivate.end()); + pImpl->m_aEmbeddedFontsToActivate.clear(); +} + void SfxMedium::AddEmbeddedFonts( const css::uno::Sequence& fonts) { @@ -4012,6 +4037,10 @@ void SfxMedium::AddEmbeddedFonts( void SfxMedium::activateEmbeddedFonts() { EmbeddedFontsHelper::activateFonts(pImpl->m_aEmbeddedFontsToActivate); + pImpl->m_aEmbeddedFonts.insert(pImpl->m_aEmbeddedFonts.end(), + pImpl->m_aEmbeddedFontsToActivate.begin(), + pImpl->m_aEmbeddedFontsToActivate.end()); + pImpl->m_aEmbeddedFontsToActivate.clear(); } bool SfxMedium::SetWritableForUserOnly( const OUString& aURL ) diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index b23396599240..db01b2e4b263 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -2375,6 +2375,10 @@ bool SfxObjectShell::DoSaveCompleted( SfxMedium* pNewMed, bool bRegisterRecent ) SfxMedium* pOld = pMedium; if ( bMedChanged ) { + if (pMedium) + { + pMedium->TransferEmbeddedFontsTo(*pNewMed); + } pMedium = pNewMed; pMedium->CanDisposeStorage_Impl( true ); } diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx index 22b7b37c5507..d01a967420c7 100644 --- a/vcl/headless/svptext.cxx +++ b/vcl/headless/svptext.cxx @@ -59,6 +59,11 @@ bool SvpSalGraphics::AddTempDevFont( vcl::font::PhysicalFontCollection* pFontCol return m_aTextRenderImpl.AddTempDevFont(pFontCollection, rFileURL, rFontName); } +bool SvpSalGraphics::RemoveTempDevFont(const OUString& rFileURL, const OUString& rFontName) +{ + return m_aTextRenderImpl.RemoveTempDevFont(rFileURL, rFontName); +} + std::unique_ptr SvpSalGraphics::GetTextLayout(int nFallbackLevel) { return m_aTextRenderImpl.GetTextLayout(nFallbackLevel); diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index c83b92839bff..837168b2ca7b 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -72,6 +72,7 @@ public: virtual void GetDevFontList( vcl::font::PhysicalFontCollection* ) override; virtual void ClearDevFontCache() override; virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; + virtual bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ) override; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; virtual void DrawTextLayout( const GenericSalLayout& ) override; diff --git a/vcl/inc/qt5/QtGraphics.hxx b/vcl/inc/qt5/QtGraphics.hxx index 2fe97adcc9d9..80ad883f4306 100644 --- a/vcl/inc/qt5/QtGraphics.hxx +++ b/vcl/inc/qt5/QtGraphics.hxx @@ -218,6 +218,7 @@ public: virtual void ClearDevFontCache() override; virtual bool AddTempDevFont(vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName) override; + virtual bool RemoveTempDevFont(const OUString& rFileURL, const OUString& rFontName) override; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; virtual void DrawTextLayout(const GenericSalLayout&) override; diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index ee40c46102ae..0fdb516d7f93 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -458,6 +458,7 @@ public: // graphics must drop any cached font info virtual void ClearDevFontCache() override; virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; + virtual bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ) override; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx index 36c8957a4dc3..0e45d881f770 100644 --- a/vcl/inc/salgdi.hxx +++ b/vcl/inc/salgdi.hxx @@ -152,6 +152,10 @@ public: const OUString& rFileURL, const OUString& rFontName ) = 0; + // Returns true, when the font was unregistered, and its file can be safely deleted + virtual bool RemoveTempDevFont(const OUString& rFileURL, + const OUString& rFontName) = 0; + virtual std::unique_ptr GetTextLayout(int nFallbackLevel) = 0; virtual void DrawTextLayout( const GenericSalLayout& ) = 0; diff --git a/vcl/inc/textrender.hxx b/vcl/inc/textrender.hxx index 96e09fd8917d..6c2731648b48 100644 --- a/vcl/inc/textrender.hxx +++ b/vcl/inc/textrender.hxx @@ -38,6 +38,7 @@ public: virtual void GetDevFontList( vcl::font::PhysicalFontCollection* ) = 0; virtual void ClearDevFontCache() = 0; virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) = 0; + virtual bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ) = 0; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) = 0; diff --git a/vcl/inc/unx/fontmanager.hxx b/vcl/inc/unx/fontmanager.hxx index e7d76bd6b659..ad54604fc019 100644 --- a/vcl/inc/unx/fontmanager.hxx +++ b/vcl/inc/unx/fontmanager.hxx @@ -117,6 +117,9 @@ class VCL_PLUGIN_PUBLIC PrintFontManager /* register an application specific font file for libfontconfig */ static void addFontconfigFile(const OString& rFile); + /* deregister an application specific font file from libfontconfig */ + static void removeFontconfigFile(std::string_view aFile); + std::set m_aPreviousLangSupportRequests; std::vector m_aCurrentRequests; Timer m_aFontInstallerTimer; @@ -128,9 +131,14 @@ public: friend class ::GenericUnixSalData; static PrintFontManager& get(); // one instance only + // There may be multiple font ids for font collections + std::vector findFontFileIDs( std::u16string_view rFileUrl ) const; + // There may be multiple font ids for font collections std::vector addFontFile( std::u16string_view rFileUrl ); + void removeFontFile( std::u16string_view rFileUrl ); + void initialize(); const PrintFont* getFont( fontID nID ) const diff --git a/vcl/inc/unx/freetypetextrender.hxx b/vcl/inc/unx/freetypetextrender.hxx index 63568db4985d..055b5ddf7a14 100644 --- a/vcl/inc/unx/freetypetextrender.hxx +++ b/vcl/inc/unx/freetypetextrender.hxx @@ -47,6 +47,7 @@ public: virtual void GetDevFontList( vcl::font::PhysicalFontCollection* ) override; virtual void ClearDevFontCache() override; virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; + virtual bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ) override; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; diff --git a/vcl/inc/unx/genpspgraphics.h b/vcl/inc/unx/genpspgraphics.h index fe904a0b6f3c..aade5d4adb3b 100644 --- a/vcl/inc/unx/genpspgraphics.h +++ b/vcl/inc/unx/genpspgraphics.h @@ -67,6 +67,8 @@ public: SAL_DLLPRIVATE virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; + SAL_DLLPRIVATE virtual bool RemoveTempDevFont(const OUString& rFileURL, + const OUString& rFontName) override; SAL_DLLPRIVATE virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx index 1a891e3d9b80..e85bad91d0c3 100644 --- a/vcl/inc/unx/glyphcache.hxx +++ b/vcl/inc/unx/glyphcache.hxx @@ -80,6 +80,7 @@ public: int nFaceNum, int nVariantNum, sal_IntPtr nFontId, const FontAttributes&); + void RemoveFontFile(sal_IntPtr nFontId); SAL_DLLPRIVATE void AnnounceFonts( vcl::font::PhysicalFontCollection* ) const; diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index fb7619801d08..81e6fa317911 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -92,6 +92,7 @@ public: virtual void GetDevFontList( vcl::font::PhysicalFontCollection* ) override; virtual void ClearDevFontCache() override; virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; + virtual bool RemoveTempDevFont( const OUString& rFileURL, const OUString& rFontName ) override; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index ed6ef27d45a1..dbeb9fc3d4d8 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -176,6 +176,7 @@ public: // graphics must drop any cached font info virtual void ClearDevFontCache() override; virtual bool AddTempDevFont( vcl::font::PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; + virtual bool RemoveTempDevFont(const OUString& rFileURL, const OUString& rFontName) override; virtual std::unique_ptr GetTextLayout(int nFallbackLevel) override; diff --git a/vcl/qt5/QtGraphics_Text.cxx b/vcl/qt5/QtGraphics_Text.cxx index 3bd998cdbdd5..23006a4b2563 100644 --- a/vcl/qt5/QtGraphics_Text.cxx +++ b/vcl/qt5/QtGraphics_Text.cxx @@ -135,6 +135,11 @@ bool QtGraphics::AddTempDevFont(vcl::font::PhysicalFontCollection*, const OUStri return false; } +bool QtGraphics::RemoveTempDevFont(const OUString& /*rFileURL*/, const OUString& /*rFontName*/) +{ + return true; // No fonts registered - no problem to remove +} + namespace { class QtCommonSalLayout : public GenericSalLayout diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx index 5c1fc31faedb..a08d17ab5942 100644 --- a/vcl/quartz/salgdi.cxx +++ b/vcl/quartz/salgdi.cxx @@ -243,6 +243,25 @@ static bool AddTempDevFont(const OUString& rFontFileURL) return success; } +static bool RemoveTempDevFont(const OUString& rFontFileURL) +{ + OUString aUSystemPath; + OSL_VERIFY(!osl::FileBase::getSystemPathFromFileURL(rFontFileURL, aUSystemPath)); + OString aCFileName = OUStringToOString(aUSystemPath, RTL_TEXTENCODING_UTF8); + + CFStringRef rFontPath + = CFStringCreateWithCString(nullptr, aCFileName.getStr(), kCFStringEncodingUTF8); + CFURLRef rFontURL + = CFURLCreateWithFileSystemPath(nullptr, rFontPath, kCFURLPOSIXPathStyle, true); + + CTFontManagerUnregisterFontsForURL(rFontURL, kCTFontManagerScopeProcess, nullptr); + + CFRelease(rFontPath); + CFRelease(rFontURL); + + return true; // Assume that even errors meant that there was nothing to remove +} + static void AddTempFontDir( const OUString &rFontDirUrl ) { osl::Directory aFontDir( rFontDirUrl ); @@ -322,6 +341,11 @@ bool AquaSalGraphics::AddTempDevFont(vcl::font::PhysicalFontCollection*, return ::AddTempDevFont(rFontFileURL); } +bool AquaSalGraphics::RemoveTempDevFont(const OUString& rFontFileURL, const OUString& /*rFontName*/) +{ + return ::RemoveTempDevFont(rFontFileURL); +} + void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) { mpBackend->drawTextLayout(rLayout); diff --git a/vcl/source/gdi/embeddedfontshelper.cxx b/vcl/source/gdi/embeddedfontshelper.cxx index 3597207b1b35..d21fa500e4e6 100644 --- a/vcl/source/gdi/embeddedfontshelper.cxx +++ b/vcl/source/gdi/embeddedfontshelper.cxx @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include #include @@ -62,6 +64,17 @@ const OUString& GetEmbeddedFontsRoot() return path; } +struct EmbeddedFontData +{ + OUString familyName; + int refcount = 0; + bool isActivated = false; +}; + +std::mutex s_EmbeddedFontsMutex; +// file URL -> EmbeddedFontData +std::unordered_map s_EmbeddedFonts; + void clearDir( const OUString& path ) { osl::Directory dir( path ); @@ -97,13 +110,12 @@ OUString fileUrlForTemporaryFont(std::u16string_view name) RTL_TEXTENCODING_UTF8); } -// Returns true when the file was written, or exactly same data was existing. +// Returns actual URL (maybe of an already existing file), or empty string on failure. // // @param name name of the font file -// @param url returns URL of a new file, or empty string (when the same file already existed). -bool writeFontBytesToFile(const std::vector& bytes, std::u16string_view name, OUString& url) +OUString writeFontBytesToFile(const std::vector& bytes, std::u16string_view name) { - url = fileUrlForTemporaryFont(name); + OUString url = fileUrlForTemporaryFont(name); std::optional file(url); auto rc = file->open(osl_File_OpenFlag_Create | osl_File_OpenFlag_Write); @@ -126,8 +138,7 @@ bool writeFontBytesToFile(const std::vector& bytes, std::u16string_view na } if (rc == osl::File::E_None && bytes2 == bytes) { - url.clear(); - return true; // OK, it's the same bytes + return url; // OK, it's the same bytes } } } @@ -137,7 +148,7 @@ bool writeFontBytesToFile(const std::vector& bytes, std::u16string_view na } if (rc != osl::File::E_None) - return false; + return {}; sal_uInt64 writtenTotal = 0; while (writtenTotal < bytes.size()) @@ -148,11 +159,11 @@ bool writeFontBytesToFile(const std::vector& bytes, std::u16string_view na { file->close(); osl::File::remove(file->getURL()); - return false; + return {}; } writtenTotal += written; } - return true; + return url; } } @@ -185,7 +196,7 @@ EmbeddedFontsHelper::~EmbeddedFontsHelper() COVERITY_NOEXCEPT_FALSE } } - // Failed to transfer the read-only fonts to the document. Activate them here. + // Failed to transfer the fonts to the document. Activate them here. activateFonts(m_aAccumulatedFonts); } @@ -282,11 +293,21 @@ bool EmbeddedFontsHelper::addEmbeddedFont( const uno::Reference< io::XInputStrea } } - OUString fileUrl; - if (!writeFontBytesToFile(fontData, Concat2View(fontName + extra), fileUrl)) + OUString fileUrl = writeFontBytesToFile(fontData, Concat2View(fontName + extra)); + if (fileUrl.isEmpty()) return false; - if (!fileUrl.isEmpty()) - m_aAccumulatedFonts.emplace_back(std::make_pair(fontName, fileUrl)); + + // Register it, and increase its refcount in s_EmbeddedFonts + { + std::unique_lock lock(s_EmbeddedFontsMutex); + auto& rData = s_EmbeddedFonts[fileUrl]; + assert(rData.familyName.isEmpty() || rData.familyName == fontName); + rData.familyName = fontName; + ++rData.refcount; + } + + m_aAccumulatedFonts.emplace_back(fontName, fileUrl); + return true; } @@ -310,11 +331,68 @@ void EmbeddedFontsHelper::activateFonts(std::vector> temp; + + { + std::unique_lock lock(s_EmbeddedFontsMutex); + // Only activate fonts that need activation. + for (const auto& pair : fonts) + { + auto it = s_EmbeddedFonts.find(pair.second); + assert(it != s_EmbeddedFonts.end()); + if (!it->second.isActivated) + { + it->second.isActivated = true; + temp.push_back(pair); + } + } + } + + if (temp.empty()) + return; + UpdateFontsGuard aUpdateFontsGuard; OutputDevice *pDevice = Application::GetDefaultDevice(); - for (const auto& [ fontName, fileUrl ] : fonts) + for (const auto& [ fontName, fileUrl ] : temp) pDevice->AddTempDevFont(fileUrl, fontName); - fonts.clear(); +} + +void EmbeddedFontsHelper::releaseFonts(const std::vector>& fonts) +{ + std::vector> unregister; + { + std::unique_lock g(s_EmbeddedFontsMutex); + for (const auto& pair : fonts) + { + auto it = s_EmbeddedFonts.find(pair.second); + if (it == s_EmbeddedFonts.end()) + { + SAL_WARN("vcl.fonts", "Trying to release a font that wasn't locked?"); + continue; + } + assert(it->second.familyName == pair.first); + + --it->second.refcount; + if (it->second.refcount == 0) + { + unregister.emplace_back(pair); + + s_EmbeddedFonts.erase(it); + } + } + } + + if (unregister.empty()) + return; + + OutputDevice* pDevice = Application::GetDefaultDevice(); + for (const auto& [ family, url ] : unregister) + { + if (pDevice->RemoveTempDevFont(url, family)) + osl::File::remove(url); + } + + OutputDevice::ImplUpdateAllFontData(true); } // Check if it's (legally) allowed to embed the font file into a document diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx index 7b45f7782893..12a097fb38d8 100644 --- a/vcl/source/outdev/font.cxx +++ b/vcl/source/outdev/font.cxx @@ -136,6 +136,15 @@ bool OutputDevice::AddTempDevFont( const OUString& rFileURL, const OUString& rFo return true; } +bool OutputDevice::RemoveTempDevFont(const OUString& rFileURL, const OUString& rFontName) +{ + if( !mpGraphics && !AcquireGraphics() ) + return true; // No graphics -> no fonts used + assert(mpGraphics); + + return mpGraphics->RemoveTempDevFont(rFileURL, rFontName); +} + bool OutputDevice::GetFontFeatures(std::vector& rFontFeatures) const { if (!ImplNewFont()) diff --git a/vcl/unx/generic/fontmanager/fontconfig.cxx b/vcl/unx/generic/fontmanager/fontconfig.cxx index 95ed5a19b5fc..642a1a7ef733 100644 --- a/vcl/unx/generic/fontmanager/fontconfig.cxx +++ b/vcl/unx/generic/fontmanager/fontconfig.cxx @@ -52,6 +52,7 @@ #include #include +#include #include #include @@ -791,6 +792,39 @@ void PrintFontManager::addFontconfigFile( const OString& rFileName ) rWrapper.addFontSet( FcSetApplication ); } +void PrintFontManager::removeFontconfigFile(std::string_view aFileName) +{ + FcFontSet* pOrig = FcConfigGetFonts(FcConfigGetCurrent(), FcSetApplication); + if (!pOrig) + return; + + std::set restoreList; + + // filter the font sets to remove the file + for (int i = 0; i < pOrig->nfont; ++i) + { + FcChar8* file = nullptr; + FcResult eFileRes = FcPatternGetString(pOrig->fonts[i], FC_FILE, 0, &file); + if (eFileRes == FcResultMatch) + { + if (std::string_view curFile(reinterpret_cast(file)); aFileName != curFile) + restoreList.emplace(curFile); + } + } + + FcConfigAppFontClear(FcConfigGetCurrent()); + + // Re-add the rest of files + for (const OString& thisFilename : restoreList) + { + FcConfigAppFontAddFile(FcConfigGetCurrent(), + reinterpret_cast(thisFilename.getStr())); + } + + FontCfgWrapper& rWrapper = FontCfgWrapper::get(); + rWrapper.addFontSet( FcSetApplication ); +} + static void addtopattern(FcPattern *pPattern, FontItalic eItalic, FontWeight eWeight, FontWidth eWidth, FontPitch ePitch) { diff --git a/vcl/unx/generic/fontmanager/fontmanager.cxx b/vcl/unx/generic/fontmanager/fontmanager.cxx index 2e454aa13d08..d755f317362a 100644 --- a/vcl/unx/generic/fontmanager/fontmanager.cxx +++ b/vcl/unx/generic/fontmanager/fontmanager.cxx @@ -135,6 +135,21 @@ int PrintFontManager::getDirectoryAtom( const OString& rDirectory ) return nAtom; } +std::vector PrintFontManager::findFontFileIDs( std::u16string_view rFileUrl ) const +{ + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); + INetURLObject aPath( rFileUrl ); + OString aName(OUStringToOString(aPath.GetLastName(INetURLObject::DecodeMechanism::WithCharset, aEncoding), aEncoding)); + OString aDir( OUStringToOString( + INetURLObject::decode( aPath.GetPath(), INetURLObject::DecodeMechanism::WithCharset, aEncoding ), aEncoding ) ); + + auto dirIt = m_aDirToAtom.find(aDir); + if (dirIt == m_aDirToAtom.end()) + return {}; + + return findFontFileIDs(dirIt->second, aName); +} + std::vector PrintFontManager::addFontFile( std::u16string_view rFileUrl ) { rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); @@ -161,6 +176,25 @@ std::vector PrintFontManager::addFontFile( std::u16string_view rFileUrl return aFontIds; } +void PrintFontManager::removeFontFile(std::u16string_view rFileUrl) +{ + INetURLObject aPath(rFileUrl); + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); + if (auto ids = findFontFileIDs(rFileUrl); !ids.empty()) + { + OString aName(OUStringToOString( + aPath.GetLastName(INetURLObject::DecodeMechanism::WithCharset, aEncoding), aEncoding)); + + for (auto nFontID : ids) + { + m_aFonts.erase(nFontID); + m_aFontFileToFontID[aName].erase(nFontID); + } + } + + removeFontconfigFile(OUStringToOString(aPath.GetFull(), aEncoding)); +} + std::vector PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile) const { std::vector aNewFonts; diff --git a/vcl/unx/generic/gdi/font.cxx b/vcl/unx/generic/gdi/font.cxx index 19887a9af230..a17c72d90a7f 100644 --- a/vcl/unx/generic/gdi/font.cxx +++ b/vcl/unx/generic/gdi/font.cxx @@ -60,6 +60,11 @@ bool X11SalGraphics::AddTempDevFont( vcl::font::PhysicalFontCollection* pFontCol return mxTextRenderImpl->AddTempDevFont(pFontCollection, rFileURL, rFontName); } +bool X11SalGraphics::RemoveTempDevFont(const OUString& rFileURL, const OUString& rFontName) +{ + return mxTextRenderImpl->RemoveTempDevFont(rFileURL, rFontName); +} + void X11SalGraphics::ClearDevFontCache() { mxTextRenderImpl->ClearDevFontCache(); diff --git a/vcl/unx/generic/gdi/freetypetextrender.cxx b/vcl/unx/generic/gdi/freetypetextrender.cxx index e5d3f3067dce..4fae167f234c 100644 --- a/vcl/unx/generic/gdi/freetypetextrender.cxx +++ b/vcl/unx/generic/gdi/freetypetextrender.cxx @@ -128,6 +128,22 @@ bool FreeTypeTextRenderImpl::AddTempDevFont(vcl::font::PhysicalFontCollection* p return true; } +bool FreeTypeTextRenderImpl::RemoveTempDevFont(const OUString& rFileURL, const OUString& /*rFontName*/) +{ + // inform PSP font manager + psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); + std::vector aFontIds = rMgr.findFontFileIDs(rFileURL); + if (aFontIds.empty()) + return true; // Nothing to remove -> safe to delete the file + + FreetypeManager& rFreetypeManager = FreetypeManager::get(); + for (auto const& nFontId : aFontIds) + rFreetypeManager.RemoveFontFile(nFontId); + + rMgr.removeFontFile(rFileURL); + return true; +} + void FreeTypeTextRenderImpl::ClearDevFontCache() { FreetypeManager::get().ClearFontCache(); diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 5745f94a223e..39c2c784b3b1 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -277,6 +277,13 @@ void FreetypeManager::AddFontFile(const OString& rNormalizedName, m_aFontInfoList[ nFontId ].reset(pFontInfo); } +void FreetypeManager::RemoveFontFile(sal_IntPtr nFontId) +{ + auto it = m_aFontInfoList.find(nFontId); + if (it != m_aFontInfoList.end()) + m_aFontInfoList.erase(it); +} + void FreetypeManager::AnnounceFonts( vcl::font::PhysicalFontCollection* pToAdd ) const { for (auto const& font : m_aFontInfoList) diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx index 66bf4524748f..ecff3110f51e 100644 --- a/vcl/unx/generic/print/genpspgraphics.cxx +++ b/vcl/unx/generic/print/genpspgraphics.cxx @@ -118,6 +118,11 @@ bool GenPspGraphics::AddTempDevFont( vcl::font::PhysicalFontCollection* pFontCol return m_aTextRenderImpl.AddTempDevFont(pFontCollection, rFileURL, rFontName); } +bool GenPspGraphics::RemoveTempDevFont(const OUString& rFileURL, const OUString& rFontName) +{ + return m_aTextRenderImpl.RemoveTempDevFont(rFileURL, rFontName); +} + void GenPspGraphics::GetDevFontList( vcl::font::PhysicalFontCollection *pFontCollection ) { m_aTextRenderImpl.GetDevFontList(pFontCollection); diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index 2ca870aad98d..c2ade38a8953 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -972,6 +972,26 @@ bool WinSalGraphics::AddTempDevFont(vcl::font::PhysicalFontCollection* pFontColl return true; } +bool WinSalGraphics::RemoveTempDevFont(const OUString& rFileURL, const OUString& /*rFontName*/) +{ + OUString path; + osl::FileBase::getSystemPathFromFileURL(rFileURL, path); + auto pSalData = GetSalData(); + for (TempFontItem** pp = &pSalData->mpTempFontItem; *pp; pp = &(*pp)->mpNextItem) + { + if ((*pp)->maFontResourcePath == path) + { + RemoveFontResourceExW(o3tl::toW(path.getStr()), FR_PRIVATE, nullptr); + auto p = *pp; + *pp = p->mpNextItem; + delete p; + return true; + } + } + SAL_WARN("vcl.fonts", "Trying to unregister an embedded font that wasn't registered?"); + return true; // It's still safe to delete the font file: we don't use it +} + void WinSalGraphics::GetDevFontList( vcl::font::PhysicalFontCollection* pFontCollection ) { // make sure all LO shared fonts are registered temporarily