writerfilter/CppunitTest_writerfilter_dmapper.mk                       |    1 
 writerfilter/qa/cppunittests/dmapper/FontTable.cxx                     |   44 
++++++++++
 writerfilter/qa/cppunittests/dmapper/data/subsetted-embedded-font.docx |binary
 writerfilter/source/dmapper/DomainMapper_Impl.cxx                      |    1 
 writerfilter/source/dmapper/DomainMapper_Impl.hxx                      |    4 
 writerfilter/source/dmapper/FontTable.cxx                              |   25 
++++-
 writerfilter/source/dmapper/FontTable.hxx                              |    4 
 writerfilter/source/ooxml/model.xml                                    |    2 
 8 files changed, 73 insertions(+), 8 deletions(-)

New commits:
commit 243ff9fa0e361ddd19b02c405319cb086628ee69
Author:     Miklos Vajna <[email protected]>
AuthorDate: Fri Jul 12 09:42:41 2024 +0200
Commit:     Caolán McNamara <[email protected]>
CommitDate: Tue Jul 16 11:47:45 2024 +0200

    tdf#162002 DOCX import: ignore subsetted embedded fonts for editing
    
    Open the bugdoc, some characters use a fallback font, some not, while
    the same font is used in Word for all characters.
    
    It turns out that the bugdoc has a subsetted embedded font, and the font
    only has 8 glyphs, which explains the inconsistent rendering.
    
    Fix the problem by ignoring subsetted fonts for the editing case: if a
    font is subsetted then only use the embedded font for viewing. First
    also had to fix up the tokenizer, as it had the wrong type for the
    subsetted attribute, so we couldn't get its boolean value
    (OOXMLStringValue doesn't override getInt(), so OOXMLValue::getInt()
    returns 0 unconditionally).
    
    Note that in theory we can have embedded fonts which are nominally
    subsetted but in practice they have a "reasonable" amount of glyphs in
    them, those are currently discarded, but should be probably still kept
    in a follow-up change.
    
    (cherry picked from commit a9f3c11375525a7708378dd3648febc40db1ad20)
    
    Conflicts:
            sw/CppunitTest_sw_writerfilter_dmapper.mk
            writerfilter/qa/cppunittests/dmapper/FontTable.cxx
            
writerfilter/qa/cppunittests/dmapper/data/subsetted-embedded-font.docx
            writerfilter/source/dmapper/DomainMapper_Impl.cxx
    
    Change-Id: I3e6dfbb246d464fede64f183a3f244edc70e7b8a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170539
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/writerfilter/CppunitTest_writerfilter_dmapper.mk 
b/writerfilter/CppunitTest_writerfilter_dmapper.mk
index dab9e3f70cc6..10a1a785ddd2 100644
--- a/writerfilter/CppunitTest_writerfilter_dmapper.mk
+++ b/writerfilter/CppunitTest_writerfilter_dmapper.mk
@@ -22,6 +22,7 @@ $(eval $(call 
gb_CppunitTest_add_exception_objects,writerfilter_dmapper, \
     writerfilter/qa/cppunittests/dmapper/DomainMapperTableManager \
     writerfilter/qa/cppunittests/dmapper/DomainMapper \
     writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl \
+       writerfilter/qa/cppunittests/dmapper/FontTable \
     writerfilter/qa/cppunittests/dmapper/GraphicImport \
     writerfilter/qa/cppunittests/dmapper/NumberingManager \
     writerfilter/qa/cppunittests/dmapper/TableManager \
diff --git a/writerfilter/qa/cppunittests/dmapper/FontTable.cxx 
b/writerfilter/qa/cppunittests/dmapper/FontTable.cxx
new file mode 100644
index 000000000000..dfd4203c522c
--- /dev/null
+++ b/writerfilter/qa/cppunittests/dmapper/FontTable.cxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/unoapi_test.hxx>
+
+#include <vcl/embeddedfontshelper.hxx>
+
+using namespace com::sun::star;
+
+namespace
+{
+/// Tests for sw/source/writerfilter/dmapper/FontTable.cxx.
+class Test : public UnoApiTest
+{
+public:
+    Test()
+        : UnoApiTest(u"/writerfilter/qa/cppunittests/dmapper/data/"_ustr)
+    {
+    }
+};
+
+CPPUNIT_TEST_FIXTURE(Test, testSubsettedEmbeddedFont)
+{
+    // Given a document with a subsetted embedded font, loaded for editing:
+    loadFromFile(u"subsetted-embedded-font.docx");
+
+    // When checking if the font is available:
+    OUString aUrl = EmbeddedFontsHelper::fontFileUrl(
+        u"IBM Plex Serif Light", FAMILY_ROMAN, ITALIC_NONE, WEIGHT_NORMAL, 
PITCH_VARIABLE,
+        EmbeddedFontsHelper::FontRights::ViewingAllowed);
+
+    // Then make sure the subsetted font is not available, given that the 
newly inserted characters
+    // during editing may be missing from the subsetted font:
+    CPPUNIT_ASSERT(aUrl.isEmpty());
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git 
a/writerfilter/qa/cppunittests/dmapper/data/subsetted-embedded-font.docx 
b/writerfilter/qa/cppunittests/dmapper/data/subsetted-embedded-font.docx
new file mode 100644
index 000000000000..85d97a1513ba
Binary files /dev/null and 
b/writerfilter/qa/cppunittests/dmapper/data/subsetted-embedded-font.docx differ
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 9e585dd6c606..4151e51533a4 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -383,6 +383,7 @@ DomainMapper_Impl::DomainMapper_Impl(
         m_bIsInTextBox(false),
         m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", 
false)),
         m_bIsAltChunk(rMediaDesc.getUnpackedValueOrDefault("AltChunkMode", 
false)),
+        m_bReadOnly(rMediaDesc.getUnpackedValueOrDefault("ReadOnly", false)),
         
m_bIsReadGlossaries(rMediaDesc.getUnpackedValueOrDefault("ReadGlossaries", 
false)),
         m_nTableCellDepth(0),
         m_bHasFtn(false),
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index cdc538368b1f..c85be001aabb 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -675,6 +675,8 @@ public:
 private:
     bool m_bIsNewDoc;
     bool m_bIsAltChunk = false;
+    /// Document is loaded for viewing, not editing.
+    bool m_bReadOnly = false;
     bool m_bIsReadGlossaries;
     std::optional<sal_Int16> m_oLineBreakClear;
 
@@ -836,7 +838,7 @@ public:
     FontTablePtr const & GetFontTable()
     {
         if(!m_pFontTable)
-            m_pFontTable = new FontTable();
+            m_pFontTable = new FontTable(m_bReadOnly);
         return m_pFontTable;
     }
     StyleSheetTablePtr const & GetStyleSheetTable()
diff --git a/writerfilter/source/dmapper/FontTable.cxx 
b/writerfilter/source/dmapper/FontTable.cxx
index 588eb841013c..e73dfb8497ad 100644
--- a/writerfilter/source/dmapper/FontTable.cxx
+++ b/writerfilter/source/dmapper/FontTable.cxx
@@ -37,14 +37,18 @@ struct FontTable_Impl
     std::unique_ptr<EmbeddedFontsHelper, 
o3tl::default_delete<EmbeddedFontsHelper>> xEmbeddedFontHelper;
     std::vector< FontEntry::Pointer_t > aFontEntries;
     FontEntry::Pointer_t pCurrentEntry;
-    FontTable_Impl() {}
+    bool m_bReadOnly;
+    FontTable_Impl(bool bReadOnly)
+        : m_bReadOnly(bReadOnly)
+    {
+    }
 };
 
-FontTable::FontTable()
+FontTable::FontTable(bool bReadOnly)
 : LoggedProperties("FontTable")
 , LoggedTable("FontTable")
 , LoggedStream("FontTable")
-, m_pImpl( new FontTable_Impl )
+, m_pImpl( new FontTable_Impl(bReadOnly) )
 {
 }
 
@@ -225,6 +229,11 @@ sal_uInt32 FontTable::size()
     return m_pImpl->aFontEntries.size();
 }
 
+bool FontTable::IsReadOnly() const
+{
+    return m_pImpl->m_bReadOnly;
+}
+
 void FontTable::addEmbeddedFont(const 
css::uno::Reference<css::io::XInputStream>& stream,
                                 const OUString& fontName, std::u16string_view 
extra,
                                 std::vector<unsigned char> const & key)
@@ -246,6 +255,12 @@ EmbeddedFontHandler::~EmbeddedFontHandler()
 {
     if( !m_inputStream.is())
         return;
+
+    if (m_bSubsetted && !m_fontTable.IsReadOnly())
+    {
+        return;
+    }
+
     std::vector< unsigned char > key( 32 );
     if( !m_fontKey.isEmpty())
     {   // key for unobfuscating
@@ -280,8 +295,8 @@ void EmbeddedFontHandler::lcl_attribute( Id name, Value& 
val )
         case NS_ooxml::LN_CT_Rel_id:
             break;
         case NS_ooxml::LN_CT_FontRel_subsetted:
-            break; // TODO? Let's just ignore this for now and hope
-                   // it doesn't break anything.
+            m_bSubsetted = static_cast<bool>(val.getInt());
+            break;
         case NS_ooxml::LN_inputstream: // the actual font data as stream
             val.getAny() >>= m_inputStream;
             break;
diff --git a/writerfilter/source/dmapper/FontTable.hxx 
b/writerfilter/source/dmapper/FontTable.hxx
index 1b6c04c73f54..0e8d93f416e7 100644
--- a/writerfilter/source/dmapper/FontTable.hxx
+++ b/writerfilter/source/dmapper/FontTable.hxx
@@ -45,7 +45,7 @@ class FontTable : public LoggedProperties, public LoggedTable
     std::unique_ptr<FontTable_Impl> m_pImpl;
 
  public:
-    FontTable();
+    FontTable(bool bReadOnly);
     virtual ~FontTable() override;
 
     sal_uInt32          size();
@@ -54,6 +54,7 @@ class FontTable : public LoggedProperties, public LoggedTable
     void addEmbeddedFont(const css::uno::Reference<css::io::XInputStream>& 
stream,
                          const OUString& fontName, std::u16string_view extra,
                          std::vector<unsigned char> const & key);
+    bool IsReadOnly() const;
 
  private:
     // Properties
@@ -98,6 +99,7 @@ private:
     std::u16string_view m_style;
     OUString m_fontKey;
     css::uno::Reference<css::io::XInputStream> m_inputStream;
+    bool m_bSubsetted = false;
 };
 
 
diff --git a/writerfilter/source/ooxml/model.xml 
b/writerfilter/source/ooxml/model.xml
index 2f84e72c0615..811eddb3186c 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -16380,7 +16380,7 @@
           <data type="string"/>
         </attribute>
         <attribute name="subsetted">
-          <data type="string"/>
+          <ref name="ST_OnOff"/>
         </attribute>
       </define>
       <define name="CT_Font">

Reply via email to