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

New commits:
commit bd6fea8f544ffd5fba18443c062d756f20fedd94
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Sep 3 08:53:47 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed Sep 3 09:29:28 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/+/190550
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

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 c260326d7cfd..f31d83be5a0d 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>
@@ -154,6 +156,43 @@ CPPUNIT_TEST_FIXTURE(Test, 
testFormatCharStyleChangeOdtImport)
     const SwFormatCharFormat& rOldCharFormat = 
pRedlineSet->Get(RES_TXTATR_CHARFMT);
     CPPUNIT_ASSERT_EQUAL(u"Strong Emphasis"_ustr, 
rOldCharFormat.GetCharFormat()->GetName());
 }
+
+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());
+    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());
+    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 eaf38350100e..211b88260a85 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