sw/qa/writerfilter/dmapper/FontTable.cxx | 36 +++++++++++++++++++++++ sw/qa/writerfilter/dmapper/data/font-family.docx |binary sw/source/writerfilter/dmapper/DomainMapper.cxx | 8 +++++ sw/source/writerfilter/dmapper/FontTable.cxx | 27 +++++++++++++++++ sw/source/writerfilter/dmapper/FontTable.hxx | 3 + sw/source/writerfilter/dmapper/PropertyIds.cxx | 1 sw/source/writerfilter/dmapper/PropertyIds.hxx | 1 7 files changed, 76 insertions(+)
New commits: commit d06de2e049761b7b9e8a95f17557d309812f7acc Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Jul 19 16:11:33 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Jul 19 22:38:42 2024 +0200 Related: tdf#162072 DOCX import: handle font family for characters Open the bugdoc, the first paragraph is meant to be sans and the second paragraph is meant to be serif, but both of them are serif. The bugdoc uses the fonts 'IBM Plex Sans' and 'IBM Plex Serif', which is not something we bundle, so the font fallback is expected, but the fallback should have a matching font family (roman vs swiss). Fix the problem by implementing support for <w:family w:val="..."> in the DOCX import, which was just ignored previously. Now the DOCX import result in on par with the ODT import result. Change-Id: I321b9fc6f63126ca5ad61af57af8a5bc7456d5b4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170772 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/writerfilter/dmapper/FontTable.cxx b/sw/qa/writerfilter/dmapper/FontTable.cxx index 2fe3dced2e1f..2d5a80ca0476 100644 --- a/sw/qa/writerfilter/dmapper/FontTable.cxx +++ b/sw/qa/writerfilter/dmapper/FontTable.cxx @@ -9,6 +9,10 @@ #include <test/unoapi_test.hxx> +#include <com/sun/star/awt/FontFamily.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/text/XTextDocument.hpp> + #include <vcl/embeddedfontshelper.hxx> using namespace com::sun::star; @@ -57,6 +61,38 @@ CPPUNIT_TEST_FIXTURE(Test, testSubsettedFullEmbeddedFont) CPPUNIT_ASSERT(!aUrl.isEmpty()); #endif } + +CPPUNIT_TEST_FIXTURE(Test, testFontFamily) +{ + // Given a document with 2 paragraphs, first is sans, second is serif: + // When loading that document: + loadFromFile(u"font-family.docx"); + + // Then make sure we import <w:family w:val="...">: + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + // First paragraph: sans. + uno::Reference<container::XEnumerationAccess> xPortionEnumAccess(xParaEnum->nextElement(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xPortionEnum = xPortionEnumAccess->createEnumeration(); + uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY); + sal_Int16 nFontFamily = awt::FontFamily::DONTKNOW; + xPortion->getPropertyValue(u"CharFontFamily"_ustr) >>= nFontFamily; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 5 (SWISS) + // - Actual : 3 (ROMAN) + // i.e. the font family was not imported, all font family was roman. + CPPUNIT_ASSERT_EQUAL(awt::FontFamily::SWISS, nFontFamily); + // Second paragraph: serif. + xPortionEnumAccess.set(xParaEnum->nextElement(), uno::UNO_QUERY); + xPortionEnum = xPortionEnumAccess->createEnumeration(); + xPortion.set(xPortionEnum->nextElement(), uno::UNO_QUERY); + nFontFamily = awt::FontFamily::DONTKNOW; + xPortion->getPropertyValue(u"CharFontFamily"_ustr) >>= nFontFamily; + CPPUNIT_ASSERT_EQUAL(awt::FontFamily::ROMAN, nFontFamily); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/writerfilter/dmapper/data/font-family.docx b/sw/qa/writerfilter/dmapper/data/font-family.docx new file mode 100644 index 000000000000..15bda10374ea Binary files /dev/null and b/sw/qa/writerfilter/dmapper/data/font-family.docx differ diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx b/sw/source/writerfilter/dmapper/DomainMapper.cxx index 8854e7ed9ece..52e3eda73187 100644 --- a/sw/source/writerfilter/dmapper/DomainMapper.cxx +++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx @@ -418,6 +418,14 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) if (m_pImpl->GetTopContext()) { m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME, uno::Any( sStringValue )); + + // Set the matching font family if we have one. + FontEntry::Pointer_t pFontEntry = m_pImpl->GetFontTable()->getFontEntryByName(sStringValue); + if (pFontEntry) + { + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_FAMILY, + uno::Any(pFontEntry->m_nFontFamily)); + } } break; case NS_ooxml::LN_CT_Fonts_asciiTheme: diff --git a/sw/source/writerfilter/dmapper/FontTable.cxx b/sw/source/writerfilter/dmapper/FontTable.cxx index 7cc8a39b3ef1..ebc7a7253247 100644 --- a/sw/source/writerfilter/dmapper/FontTable.cxx +++ b/sw/source/writerfilter/dmapper/FontTable.cxx @@ -136,7 +136,21 @@ void FontTable::lcl_sprm(Sprm& rSprm) case NS_ooxml::LN_CT_Font_panose1: break; case NS_ooxml::LN_CT_Font_family: + { + Value::Pointer_t pValue = rSprm.getValue(); + sal_Int32 nIntValue = pValue ? pValue->getInt() : 0; + // Map OOXML's ST_FontFamily to UNO's awt::FontFamily. + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_FontFamily_roman: + m_pImpl->pCurrentEntry->m_nFontFamily = awt::FontFamily::ROMAN; + break; + case NS_ooxml::LN_Value_ST_FontFamily_swiss: + m_pImpl->pCurrentEntry->m_nFontFamily = awt::FontFamily::SWISS; + break; + } break; + } case NS_ooxml::LN_CT_Font_sig: break; case NS_ooxml::LN_CT_Font_notTrueType: @@ -229,6 +243,19 @@ sal_uInt32 FontTable::size() return m_pImpl->aFontEntries.size(); } +FontEntry::Pointer_t FontTable::getFontEntryByName(std::u16string_view rName) +{ + for (const auto& pEntry : m_pImpl->aFontEntries) + { + if (pEntry->sFontName == rName) + { + return pEntry; + } + } + + return nullptr; +} + bool FontTable::IsReadOnly() const { return m_pImpl->m_bReadOnly; diff --git a/sw/source/writerfilter/dmapper/FontTable.hxx b/sw/source/writerfilter/dmapper/FontTable.hxx index babb43d8aebb..99c23a00cb36 100644 --- a/sw/source/writerfilter/dmapper/FontTable.hxx +++ b/sw/source/writerfilter/dmapper/FontTable.hxx @@ -23,6 +23,7 @@ #include <vector> #include "LoggedResources.hxx" #include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/awt/FontFamily.hpp> namespace writerfilter::dmapper { @@ -33,6 +34,7 @@ struct FontEntry : public virtual SvRefBase typedef tools::SvRef<FontEntry> Pointer_t; OUString sFontName; + sal_Int16 m_nFontFamily = css::awt::FontFamily::DONTKNOW; sal_Int32 nTextEncoding; FontEntry() : nTextEncoding( RTL_TEXTENCODING_DONTKNOW ) @@ -50,6 +52,7 @@ class FontTable : public LoggedProperties, public LoggedTable sal_uInt32 size(); FontEntry::Pointer_t getFontEntry(sal_uInt32 nIndex); + FontEntry::Pointer_t getFontEntryByName(std::u16string_view rName); void addEmbeddedFont(const css::uno::Reference<css::io::XInputStream>& stream, const OUString& fontName, std::u16string_view extra, diff --git a/sw/source/writerfilter/dmapper/PropertyIds.cxx b/sw/source/writerfilter/dmapper/PropertyIds.cxx index 394a3fd633b5..68e1e1cb8c3a 100644 --- a/sw/source/writerfilter/dmapper/PropertyIds.cxx +++ b/sw/source/writerfilter/dmapper/PropertyIds.cxx @@ -395,6 +395,7 @@ OUString getPropertyName( PropertyIds eId ) { PROP_PARA_CONNECT_BORDERS, u"ParaIsConnectBorder"}, { PROP_DECORATIVE, u"Decorative"}, { PROP_PAPER_TRAY, u"PrinterPaperTray"}, + { PROP_CHAR_FONT_FAMILY, u"CharFontFamily"}, }; auto iterator = constPropertyMap.find(eId); if (iterator != constPropertyMap.end()) diff --git a/sw/source/writerfilter/dmapper/PropertyIds.hxx b/sw/source/writerfilter/dmapper/PropertyIds.hxx index 82ffb1ac35d4..72f3ffb149ab 100644 --- a/sw/source/writerfilter/dmapper/PropertyIds.hxx +++ b/sw/source/writerfilter/dmapper/PropertyIds.hxx @@ -397,6 +397,7 @@ enum PropertyIds ,PROP_RTL_GUTTER ,PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF ,PROP_PARA_CONNECT_BORDERS + ,PROP_CHAR_FONT_FAMILY }; //Returns the UNO string equivalent to eId.