sw/qa/extras/rtfexport/data/tdf167679.fodt |   25 +++++++
 sw/qa/extras/rtfexport/rtfexport8.cxx      |   95 +++++++++++++++++++++++++++++
 sw/source/filter/ww8/ww8atr.cxx            |   16 +---
 3 files changed, 126 insertions(+), 10 deletions(-)

New commits:
commit a71995f1cac713cec0dcaed98ba498650b65deb8
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Jul 26 21:33:06 2025 +0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Jul 28 10:30:30 2025 +0200

    tdf#167679: RTF already can export rdrnone
    
    In commit f84b33275f6cce21e93e5dd20f3de5df84df0276 (tdf#129522
    ww8import/export: allow char shadow_NONE overrides, 2020-01-04),
    export of char shadow was implemented, which made CharBorder to
    be called for missing borderline. But it made an exception for
    RTF, because at that time, its code couldn't handle that.
    
    In commit eca3ce35fe9a346965a32f42d02cb6d3f5a3982f (tdf#129631
    writerfilter,sw: RTF import of invalid border..., 2022-08-11),
    RTF export got ability to handle that.
    
    Removal of the exception for RTF fixed missing export of "no
    border" and "no shadow" character formatting.
    
    Change-Id: I5f23b09558d32b403e0c26c727ee01f79374e54d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188426
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/rtfexport/data/tdf167679.fodt 
b/sw/qa/extras/rtfexport/data/tdf167679.fodt
new file mode 100644
index 000000000000..fad1dacf5b45
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf167679.fodt
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Serif" 
svg:font-family="&apos;Liberation Serif&apos;" 
style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="paragraph">
+   <style:text-properties style:font-name="Liberation Serif" 
fo:font-size="12pt"/>
+  </style:default-style>
+  <style:style style:name="border" style:family="text">
+   <style:text-properties loext:padding="0.5mm" loext:border="0.11pt solid 
#FF0000" loext:shadow="#808080 5pt 5pt"/>
+  </style:style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties loext:padding="0.5mm" loext:border="none" 
loext:shadow="none"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <text:p>s<text:span text:style-name="border">om<text:span 
text:style-name="T1">eth</text:span>in</text:span>g</text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx 
b/sw/qa/extras/rtfexport/rtfexport8.cxx
index 5580c1f65dae..fa7f1a17cb36 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -22,6 +22,7 @@
 #include <com/sun/star/text/XTextDocument.hpp>
 #include <com/sun/star/style/ParagraphAdjust.hpp>
 #include <com/sun/star/style/TabStop.hpp>
+#include <com/sun/star/table/ShadowFormat.hpp>
 
 #include <basegfx/utils/gradienttools.hxx>
 #include <comphelper/sequenceashashmap.hxx>
@@ -909,6 +910,100 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf167661)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf167679)
+{
+    // Given a document with a char style with a border with a shadow, and a 
direct formatting
+    // applied over it, which turns off the border and the shadow:
+    createSwDoc("tdf167679.fodt");
+
+    {
+        auto xRun = getRun(getParagraph(1), 1, u"s"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0x000000, 0, 0, 0, 
32767, 0), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_NONE, aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 2, u"om"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0xFF0000, 0, 4, 0, 0, 
4), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, 
aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 3, u"eth"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0x000000, 0, 0, 0, 
32767, 0), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_NONE, aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 4, u"in"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0xFF0000, 0, 4, 0, 0, 
4), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, 
aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 5, u"g"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0x000000, 0, 0, 0, 
32767, 0), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_NONE, aShadow.Location);
+    }
+
+    // Check that after export to RTF, the area in the middle still has no 
border
+    saveAndReload(mpFilter);
+
+    {
+        auto xRun = getRun(getParagraph(1), 1, u"s"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0x000000, 0, 0, 0, 
32767, 0), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_NONE, aShadow.Location);
+    }
+    {
+        // Without a fix, this failed, because the second run was "omethin": 
the middle
+        // direct formatting that cancelled the border didn't round-trip.
+        auto xRun = getRun(getParagraph(1), 2, u"om"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0xFF0000, 0, 4, 0, 0, 
4), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, 
aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 3, u"eth"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0x000000, 0, 0, 0, 
32767, 0), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_NONE, aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 4, u"in"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0xFF0000, 0, 4, 0, 0, 
4), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, 
aShadow.Location);
+    }
+    {
+        auto xRun = getRun(getParagraph(1), 5, u"g"_ustr);
+        auto aBorder = getProperty<table::BorderLine2>(xRun, 
u"CharTopBorder"_ustr);
+        CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0x000000, 0, 0, 0, 
32767, 0), aBorder);
+
+        auto aShadow = getProperty<table::ShadowFormat>(xRun, 
u"CharShadowFormat"_ustr);
+        CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_NONE, aShadow.Location);
+    }
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index 7c836fffdf8e..d85f9bb8d987 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -5998,17 +5998,13 @@ void AttributeOutputBase::FormatCharBorder( const 
SvxBoxItem& rBox )
        nDist = rBox.GetDistance( SvxBoxItemLine::RIGHT );
     }
 
-    // RTF: avoid regressions since RTF doesn't know how to export a 
border_NONE style-override
-    if( pBorderLine || GetExport().GetExportFormat() != 
MSWordExportBase::ExportFormat::RTF )
-    {
-        const SfxPoolItem* pItem = GetExport().HasItem( RES_CHRATR_SHADOW );
-        const SvxShadowItem* pShadowItem = static_cast<const 
SvxShadowItem*>(pItem);
-        const bool bShadow = pBorderLine &&
-            pShadowItem && pShadowItem->GetLocation() != 
SvxShadowLocation::NONE &&
-            pShadowItem->GetWidth() > 0;
+    const SfxPoolItem* pItem = GetExport().HasItem( RES_CHRATR_SHADOW );
+    const SvxShadowItem* pShadowItem = static_cast<const 
SvxShadowItem*>(pItem);
+    const bool bShadow = pBorderLine &&
+        pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE &&
+        pShadowItem->GetWidth() > 0;
 
-        CharBorder( pBorderLine, nDist, bShadow );
-    }
+    CharBorder( pBorderLine, nDist, bShadow );
 }
 
 /*

Reply via email to