writerfilter/qa/cppunittests/dmapper/FontTable.cxx | 36 +++++++++++++ writerfilter/qa/cppunittests/dmapper/data/font-family.docx |binary writerfilter/source/dmapper/DomainMapper.cxx | 8 ++ writerfilter/source/dmapper/FontTable.cxx | 27 +++++++++ writerfilter/source/dmapper/FontTable.hxx | 3 + writerfilter/source/dmapper/PropertyIds.cxx | 1 writerfilter/source/dmapper/PropertyIds.hxx | 1 7 files changed, 76 insertions(+)
New commits: commit 143475dbdf9eae442d93382c0a5bff5578801452 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Jul 19 16:11:33 2024 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Tue Jul 30 09:15:23 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. (cherry picked from commit d06de2e049761b7b9e8a95f17557d309812f7acc) Conflicts: writerfilter/qa/cppunittests/dmapper/data/font-family.docx Change-Id: I321b9fc6f63126ca5ad61af57af8a5bc7456d5b4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171227 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/writerfilter/qa/cppunittests/dmapper/FontTable.cxx b/writerfilter/qa/cppunittests/dmapper/FontTable.cxx index 33019c5350c6..d3b237e0a8ce 100644 --- a/writerfilter/qa/cppunittests/dmapper/FontTable.cxx +++ b/writerfilter/qa/cppunittests/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/writerfilter/qa/cppunittests/dmapper/data/font-family.docx b/writerfilter/qa/cppunittests/dmapper/data/font-family.docx new file mode 100644 index 000000000000..15bda10374ea Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/font-family.docx differ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index b4e61895a847..83f670696f0a 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -422,6 +422,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/writerfilter/source/dmapper/FontTable.cxx b/writerfilter/source/dmapper/FontTable.cxx index 458df2fb65c0..e45f9aab0ea8 100644 --- a/writerfilter/source/dmapper/FontTable.cxx +++ b/writerfilter/source/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/writerfilter/source/dmapper/FontTable.hxx b/writerfilter/source/dmapper/FontTable.hxx index a364c6d97c54..0cc5162425ef 100644 --- a/writerfilter/source/dmapper/FontTable.hxx +++ b/writerfilter/source/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/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx index 0b599a0a4a28..c37726d324c5 100644 --- a/writerfilter/source/dmapper/PropertyIds.cxx +++ b/writerfilter/source/dmapper/PropertyIds.cxx @@ -393,6 +393,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/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx index ba62c34000ed..7c286f26214a 100644 --- a/writerfilter/source/dmapper/PropertyIds.hxx +++ b/writerfilter/source/dmapper/PropertyIds.hxx @@ -395,6 +395,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.