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.

Reply via email to