include/xmloff/xmlexp.hxx | 7 +++---- sc/inc/xmlwrap.hxx | 2 +- sc/source/filter/xml/xmlwrap.cxx | 4 ++-- sd/source/filter/xml/sdxmlwrp.cxx | 6 +++--- sw/qa/extras/uiwriter/uiwriter6.cxx | 12 ++++++------ sw/source/filter/xml/wrtxml.cxx | 4 ++-- sw/source/filter/xml/wrtxml.hxx | 2 +- xmloff/source/style/XMLFontAutoStylePool.cxx | 16 ++++++---------- 8 files changed, 24 insertions(+), 29 deletions(-)
New commits: commit 8ebe1e51ea9be20dd3e2279359ca0bebc9beb05c Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sat May 24 01:32:06 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri May 23 23:58:36 2025 +0200 Related: tdf#166627 Write font-face-src for each mention of embedded font Before commit e61a179b4ff8ce2072c3c0780628eb38c7a43529 (tdf#166627: embed fonts everywhere we emit font data, 2025-05-23), embedding of fonts only happened during export of content.xml, to avoid complexity of shared data between different instances of SvXMLExport, created separately per stream. The said commit introduced a way to pass the data between these instances, and embedding now is done by any SvXMLExport instance that needs to emit font-face-decls. Currently, only the first declaration of a used embedded font gets its font-face-src. But this is wrong, when the same embedded font in another stream, where it is also used, does not reference its files. This patch allows all streams to emit font-face-src for all fonts used in it. File duplication in ZIP is avoided by passing the embedded file information between SvXMLExport, with font file hash and its path in ZIP, instead of font names. Change-Id: I7a62e50c086d8741dbc8aadf61d0f008bad916ff Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185720 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/include/xmloff/xmlexp.hxx b/include/xmloff/xmlexp.hxx index ce10b5b2b60f..7f9e9dbe5d8c 100644 --- a/include/xmloff/xmlexp.hxx +++ b/include/xmloff/xmlexp.hxx @@ -164,9 +164,8 @@ class XMLOFF_DLLPUBLIC SvXMLExport : public cppu::WeakImplHelper< const OUString msWS; // " " + // A map of font hashes and names that were already embedded, including previous passes std::unordered_map<OString, OUString> m_aEmbeddedFontFiles; - // A list of font names that were already embedded, including previous passes - std::unordered_set<OUString> m_aEmbeddedFontNames; // Shapes in Writer cannot be named via context menu (#i51726#) SvtModuleOptions::EFactory meModelType; @@ -317,8 +316,8 @@ public: // doesn't handle some style-specific content like headers/footers. These methods are for // passing the "already embedded" information from one instance to another. - std::vector<OUString> getEmbeddedFontNames() const; - void setEmbeddedFontNames(const std::vector<OUString>&); + std::unordered_map<OString, OUString> getEmbeddedFontFiles() const; + void setEmbeddedFontFiles(const std::unordered_map<OString, OUString>&); // XExporter virtual void SAL_CALL setSourceDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override; diff --git a/sc/inc/xmlwrap.hxx b/sc/inc/xmlwrap.hxx index 618cc995c71c..f7b49cfa37b5 100644 --- a/sc/inc/xmlwrap.hxx +++ b/sc/inc/xmlwrap.hxx @@ -63,7 +63,7 @@ class ScXMLImportWrapper SfxMedium* pMedium; css::uno::Reference< css::embed::XStorage > xStorage; - std::vector<OUString> maEmbeddedFontNames; + std::unordered_map<OString, OUString> maEmbeddedFontFiles; css::uno::Reference< css::task::XStatusIndicator> GetStatusIndicator() const; diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx index cfeb7a991bad..f6e9d7ef466b 100644 --- a/sc/source/filter/xml/xmlwrap.cxx +++ b/sc/source/filter/xml/xmlwrap.cxx @@ -650,7 +650,7 @@ bool ScXMLImportWrapper::ExportToComponent(const uno::Reference<uno::XComponentC ScXMLExport* pExport = static_cast<ScXMLExport*>(dynamic_cast<SvXMLExport*>(xFilter.get())); assert(pExport && "can only succeed"); pExport->SetSharedData(std::move(pSharedData)); - pExport->setEmbeddedFontNames(maEmbeddedFontNames); + pExport->setEmbeddedFontFiles(maEmbeddedFontFiles); // if there are sheets to copy, get the source stream if ( sName == "content.xml" && lcl_HasValidStream(rDoc) && ( pExport->getExportFlags() & SvXMLExportFlags::OASIS ) ) @@ -698,7 +698,7 @@ bool ScXMLImportWrapper::ExportToComponent(const uno::Reference<uno::XComponentC else bRet = xFilter->filter( aDescriptor ); - maEmbeddedFontNames = pExport->getEmbeddedFontNames(); + maEmbeddedFontFiles = pExport->getEmbeddedFontFiles(); pSharedData = pExport->ReleaseSharedData(); } diff --git a/sd/source/filter/xml/sdxmlwrp.cxx b/sd/source/filter/xml/sdxmlwrp.cxx index d8cd04671945..caf15884c10f 100644 --- a/sd/source/filter/xml/sdxmlwrp.cxx +++ b/sd/source/filter/xml/sdxmlwrp.cxx @@ -896,7 +896,7 @@ bool SdXMLFilter::Export() aServices[i].mpStream = nullptr; XML_SERVICEMAP* pServices = aServices; - std::vector<OUString> aEmbeddedFontNames; + std::unordered_map<OString, OUString> maEmbeddedFontFiles; // doc export do @@ -954,13 +954,13 @@ bool SdXMLFilter::Export() auto pFilter = dynamic_cast<SvXMLExport*>(xFilter.get()); if (pFilter) { - pFilter->setEmbeddedFontNames(aEmbeddedFontNames); + pFilter->setEmbeddedFontFiles(maEmbeddedFontFiles); } // outputstream will be closed by SAX parser bDocRet = xFilter->filter( aDescriptor ); if (pFilter) { - aEmbeddedFontNames = pFilter->getEmbeddedFontNames(); + maEmbeddedFontFiles = pFilter->getEmbeddedFontFiles(); } } } diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx index 438e588eb0b9..2c0069a7e65a 100644 --- a/sw/qa/extras/uiwriter/uiwriter6.cxx +++ b/sw/qa/extras/uiwriter/uiwriter6.cxx @@ -2361,7 +2361,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testFontEmbedding) assertXPath(pXmlDoc, prefix + "/svg:font-face-src['CASE 2']", 1); } - // Check content - No font-face-src nodes should be present + // Check content - font-face-src should be present for all fonts pXmlDoc = parseExport(u"content.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); @@ -2371,7 +2371,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testFontEmbedding) { OString prefix = aContentBaseXpath + "/style:font-face[@style:name='" + fontName + "']"; assertXPath(pXmlDoc, prefix + "['CASE 2']"); - assertXPath(pXmlDoc, prefix + "/svg:font-face-src['CASE 2']", 0); + assertXPath(pXmlDoc, prefix + "/svg:font-face-src['CASE 2']", 1); } // CASE 3 - font embedding enabled, embed only used fonts enabled @@ -2423,19 +2423,19 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testFontEmbedding) assertXPath(pXmlDoc, prefix + "/svg:font-face-src['CASE 3']", 1); } - // Check content - font-face-src should be present only for Carlito fonts + // Check content - font-face-src should be present only for Carlito and Liberation Serif fonts + // Note that the used sets of fonts are different for styles.xml and content.xml pXmlDoc = parseExport(u"content.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); assertXPath(pXmlDoc, aContentBaseXpath + "/style:font-face['CASE 3']", 6); - for (auto fontName : { "Caladea", "Liberation Sans", "Liberation Sans1", "Liberation Serif", - "Liberation Serif1" }) + for (auto fontName : { "Caladea", "Liberation Sans", "Liberation Sans1" }) { OString prefix = aContentBaseXpath + "/style:font-face[@style:name='" + fontName + "']"; assertXPath(pXmlDoc, prefix + "['CASE 3']"); assertXPath(pXmlDoc, prefix + "/svg:font-face-src['CASE 3']", 0); } - for (auto fontName : { "Carlito" }) + for (auto fontName : { "Carlito", "Liberation Serif", "Liberation Serif1" }) { OString prefix = aContentBaseXpath + "/style:font-face[@style:name='" + fontName + "']"; assertXPath(pXmlDoc, prefix + "['CASE 3']"); diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx index 66faa6342428..2f5e049ea581 100644 --- a/sw/source/filter/xml/wrtxml.cxx +++ b/sw/source/filter/xml/wrtxml.cxx @@ -579,12 +579,12 @@ bool SwXMLWriter::WriteThroughComponent( if (pFilter) { pFilter->SetLibreOfficeKitNotifier(SfxViewShell::Current()); - pFilter->setEmbeddedFontNames(maEmbeddedFontNames); + pFilter->setEmbeddedFontFiles(maEmbeddedFontFiles); } bool result = xFilter->filter( rMediaDesc ); if (pFilter) { - maEmbeddedFontNames = pFilter->getEmbeddedFontNames(); + maEmbeddedFontFiles = pFilter->getEmbeddedFontFiles(); } return result; } diff --git a/sw/source/filter/xml/wrtxml.hxx b/sw/source/filter/xml/wrtxml.hxx index 850de4780db9..57a8c31980fe 100644 --- a/sw/source/filter/xml/wrtxml.hxx +++ b/sw/source/filter/xml/wrtxml.hxx @@ -53,7 +53,7 @@ public: virtual ErrCodeMsg Write( SwPaM&, SfxMedium&, const OUString* ) override; private: - std::vector<OUString> maEmbeddedFontNames; + std::unordered_map<OString, OUString> maEmbeddedFontFiles; // helper methods to write XML streams diff --git a/xmloff/source/style/XMLFontAutoStylePool.cxx b/xmloff/source/style/XMLFontAutoStylePool.cxx index e2050423b047..3034aef14ee9 100644 --- a/xmloff/source/style/XMLFontAutoStylePool.cxx +++ b/xmloff/source/style/XMLFontAutoStylePool.cxx @@ -425,10 +425,8 @@ void SvXMLExport::exportFonts(const std::vector<XMLFontAutoStylePoolEntry_Impl*> SvXMLElementExport aElement(*this, XML_NAMESPACE_STYLE, XML_FONT_FACE, true, true); - // When embedding is requested, and embedded only is not set or font is used, and the font - // was not embedded already in a different pass - if (bEmbedFonts && (!bEmbedUsedOnly || aUsedFontNames.contains(pEntry->GetFamilyName())) - && !m_aEmbeddedFontNames.contains(pEntry->GetName())) + // When embedding is requested, and embedded only is not set or font is used + if (bEmbedFonts && (!bEmbedUsedOnly || aUsedFontNames.contains(pEntry->GetFamilyName()))) { const bool bExportFlat(getExportFlags() & SvXMLExportFlags::EMBEDDED); @@ -467,7 +465,6 @@ void SvXMLExport::exportFonts(const std::vector<XMLFontAutoStylePoolEntry_Impl*> } if (!aEmbeddedFonts.empty()) { - m_aEmbeddedFontNames.insert(pEntry->GetName()); SvXMLElementExport fontFaceSrc(*this, XML_NAMESPACE_SVG, XML_FONT_FACE_SRC, true, true); for (EmbeddedFontInfo const & rEmbeddedFont : aEmbeddedFonts) { @@ -516,15 +513,14 @@ void SvXMLExport::exportFonts(const std::vector<XMLFontAutoStylePoolEntry_Impl*> } } -std::vector<OUString> SvXMLExport::getEmbeddedFontNames() const +std::unordered_map<OString, OUString> SvXMLExport::getEmbeddedFontFiles() const { - return std::vector(m_aEmbeddedFontNames.begin(), m_aEmbeddedFontNames.end()); + return m_aEmbeddedFontFiles; } -void SvXMLExport::setEmbeddedFontNames(const std::vector<OUString>& newNames) +void SvXMLExport::setEmbeddedFontFiles(const std::unordered_map<OString, OUString>& value) { - m_aEmbeddedFontNames.clear(); - m_aEmbeddedFontNames.insert(newNames.begin(), newNames.end()); + m_aEmbeddedFontFiles = value; } void XMLFontAutoStylePool::exportXML()