sw/qa/filter/xml/data/format-charstyle-direct.odt |binary
 sw/qa/filter/xml/xml.cxx                          |   40 ++++++++++++++++++++++
 sw/source/filter/xml/XMLRedlineImportHelper.cxx   |   20 ++++++++---
 3 files changed, 55 insertions(+), 5 deletions(-)

New commits:
commit e1e36df4fc2e7b8aaca82bbb00cfb9a414b0385a
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Sep 3 08:53:47 2025 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Sep 10 11:10:06 2025 +0200

    tdf#167761 sw format redline, char style+direct: add ODT import
    
    Open the bugdoc, it contains a format redline that changes the character
    style from Strong to Quote and the font size from 24 to 36. Revert the
    redline, the char style goes back to Strong, but the font size is 12,
    not 24.
    
    The problem is that only the char style was imported in
    XMLRedlineImportHelper::InsertIntoDocument(), because direct formatting
    is only handled when we have no char style.
    
    Fix the problem by creating an empty item set earlier, similar to how
    lcl_SetRedline() does it in the UI code, then both the char style and
    direct format can go into that item set.
    
    The format redline's ODT/DOCX filter is now in a reasonable shape with
    this.
    
    Change-Id: I28e2a43e218a319045649612e7492821e72649b5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190551
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit bbebb3908ff9a9c384a475737ead537906517387)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190556
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sw/qa/filter/xml/data/format-charstyle-direct.odt 
b/sw/qa/filter/xml/data/format-charstyle-direct.odt
new file mode 100644
index 000000000000..40b6df9528f0
Binary files /dev/null and b/sw/qa/filter/xml/data/format-charstyle-direct.odt 
differ
diff --git a/sw/qa/filter/xml/xml.cxx b/sw/qa/filter/xml/xml.cxx
index de92d086f482..6ab6f7595720 100644
--- a/sw/qa/filter/xml/xml.cxx
+++ b/sw/qa/filter/xml/xml.cxx
@@ -9,6 +9,8 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <editeng/fhgtitem.hxx>
+
 #include <frameformats.hxx>
 #include <frmatr.hxx>
 #include <swtable.hxx>
@@ -155,6 +157,44 @@ CPPUNIT_TEST_FIXTURE(Test, 
testFormatCharStyleChangeOdtImport)
     CPPUNIT_ASSERT_EQUAL(u"Strong Emphasis"_ustr,
                          rOldCharFormat.GetCharFormat()->GetName().toString());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFormatCharstyleDirectOdtImport)
+{
+    // Given a document with a format redline, containing a char style change 
(strong -> quote) and
+    // a font size change (24 -> 36pt):
+    // When importing that document:
+    createSwDoc("format-charstyle-direct.odt");
+
+    // Then make sure the model has the new style name & new font size, the 
redline has the old
+    // style name & old font size:
+    SwDocShell* pDocShell = getSwDocShell();
+    SwDoc* pDoc = pDocShell->GetDoc();
+    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+    pWrtShell->SttEndDoc(/*bStt=*/false);
+    SfxItemSetFixed<RES_CHRATR_FONTSIZE, RES_TXTATR_CHARFMT> 
aSet(pDoc->GetAttrPool());
+    pWrtShell->GetCurAttr(aSet);
+    const SwFormatCharFormat& rNewCharFormat = aSet.Get(RES_TXTATR_CHARFMT);
+    CPPUNIT_ASSERT_EQUAL(u"Quote Char"_ustr, 
rNewCharFormat.GetCharFormat()->GetName().toString());
+    const SvxFontHeightItem& rNewFontSize = aSet.Get(RES_CHRATR_FONTSIZE);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(36 * 20), 
rNewFontSize.GetHeight());
+    const IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
+    const SwRedlineTable& rRedlineTable = rIDRA.GetRedlineTable();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlineTable.size());
+    const SwRangeRedline* pRedline = rRedlineTable[0];
+    auto pExtraData = dynamic_cast<const 
SwRedlineExtraData_FormatColl*>(pRedline->GetExtraData());
+    CPPUNIT_ASSERT(pExtraData);
+    std::shared_ptr<SfxItemSet> pRedlineSet = pExtraData->GetItemSet();
+    CPPUNIT_ASSERT(pRedlineSet);
+    const SwFormatCharFormat& rOldCharFormat = 
pRedlineSet->Get(RES_TXTATR_CHARFMT);
+    CPPUNIT_ASSERT_EQUAL(u"Strong Emphasis"_ustr,
+                         rOldCharFormat.GetCharFormat()->GetName().toString());
+    const SvxFontHeightItem& rOldFontSize = 
pRedlineSet->Get(RES_CHRATR_FONTSIZE);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 480
+    // - Actual  : 240
+    // i.e. the redline didn't contain a correct old font size (direct format).
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(24 * 20), 
rOldFontSize.GetHeight());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.cxx 
b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
index eed1fd273e91..bf6ec7a1e2ca 100644
--- a/sw/source/filter/xml/XMLRedlineImportHelper.cxx
+++ b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
@@ -798,22 +798,32 @@ void 
XMLRedlineImportHelper::InsertIntoDocument(RedlineInfo* pRedlineInfo)
         }
 
         // Create the redline's extra data if we have a matching autostyle.
-        std::shared_ptr<SfxItemSet> pAutoStyle;
         IStyleAccess& rStyleAccess = pDoc->GetIStyleAccess();
+        SfxItemSetFixed<RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1, 
RES_UNKNOWNATR_BEGIN,
+                        RES_UNKNOWNATR_END - 1>
+            aItemSet(pDoc->GetAttrPool());
         if (!pRedlineInfo->m_aStyleName.isEmpty())
         {
             // Named character style.
-            SfxItemSetFixed<RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT> 
aItemSet(pDoc->GetAttrPool());
             uno::Any aStyleName;
             aStyleName <<= pRedlineInfo->m_aStyleName;
             SwUnoCursorHelper::SetCharStyle(*pDoc, aStyleName, aItemSet);
-            pAutoStyle = rStyleAccess.getAutomaticStyle(aItemSet, 
IStyleAccess::AUTO_STYLE_CHAR);
         }
-        else if (!pRedlineInfo->m_aAutoName.isEmpty())
+        if (!pRedlineInfo->m_aAutoName.isEmpty())
         {
             // Just a set of character properties with an automatic name.
-            pAutoStyle
+            std::shared_ptr<SfxItemSet> pAutoStyle
                 = rStyleAccess.getByName(pRedlineInfo->m_aAutoName, 
IStyleAccess::AUTO_STYLE_CHAR);
+            if (pAutoStyle)
+            {
+                aItemSet.Put(*pAutoStyle);
+            }
+        }
+        std::shared_ptr<SfxItemSet> pAutoStyle;
+        if (aItemSet.Count() > 0)
+        {
+            // Have a named style or direct format, create an automatic style.
+            pAutoStyle = rStyleAccess.getAutomaticStyle(aItemSet, 
IStyleAccess::AUTO_STYLE_CHAR);
         }
         if (pAutoStyle)
         {

Reply via email to