sw/qa/core/draw/data/tdf107727_FrameBorder.odt |binary
 sw/qa/core/draw/draw.cxx                       |   43 ++++++++++++++++++++
 sw/source/filter/ww8/rtfattributeoutput.cxx    |   52 ++++++++++++++++---------
 3 files changed, 78 insertions(+), 17 deletions(-)

New commits:
commit 9877a0190e43241f4a5102e5d9cc7181f91d5a6f
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Tue Feb 1 20:38:07 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Feb 2 08:38:11 2022 +0100

    tdf#107727 disable border in RTF export if not drawn
    
    A border of a text frame is not drawn, if it is really disabled or if
    its line style is None. The patch considers both cases. Previously the
    first case was missing.
    
    LO can disable single border lines and single border lines can have
    different styles. The patch uses a border line now, that is really
    drawn, to get the color and width. It uses the first one in order
    top, bottom, left, right.
    
    In theory RTF can describe disabling single border lines by using the
    flags fTopLine, fBottomLine, fLeftLine or fRightLine. But Word has
    only the ability to enable all or none of the border lines for an old
    kind text box as contained in an rtf-document. The current patch uses
    therefore this all-or-none approach too. It enables border if at least
    one is actually drawn, because that keeps the style settings for that
    border line. Previously all four border lines need to be drawn.
    
    If it is changed to use the flags fTopLine, fBottomLine, fLeftLine
    and fRightLine on export, then it would be possible to recover showing
    only single border lines on reimport. But that is out of scope here.
    
    Change-Id: Ib78604def154c133d3c93bc75a38731eb6b02294
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129305
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/draw/data/tdf107727_FrameBorder.odt 
b/sw/qa/core/draw/data/tdf107727_FrameBorder.odt
new file mode 100644
index 000000000000..6b7bc3a375fa
Binary files /dev/null and b/sw/qa/core/draw/data/tdf107727_FrameBorder.odt 
differ
diff --git a/sw/qa/core/draw/draw.cxx b/sw/qa/core/draw/draw.cxx
index 97b6a2bb7d79..c2514808f8e4 100644
--- a/sw/qa/core/draw/draw.cxx
+++ b/sw/qa/core/draw/draw.cxx
@@ -10,6 +10,7 @@
 #include <swmodeltestbase.hxx>
 
 #include <svx/svdpage.hxx>
+#include <unotools/mediadescriptor.hxx>
 
 #include <IDocumentDrawModelAccess.hxx>
 #include <docsh.hxx>
@@ -18,6 +19,10 @@
 #include <frameformats.hxx>
 #include <textboxhelper.hxx>
 
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/text/XTextFramesSupplier.hpp>
+
 constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/core/draw/data/";
 
 /// Covers sw/source/core/draw/ fixes.
@@ -98,6 +103,44 @@ CPPUNIT_TEST_FIXTURE(SwCoreDrawTest, testTextboxUndoOrdNum)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreDrawTest, testTdf107727FrameBorder)
+{
+    // Load a document with a textframe without border, one with only left 
border
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"tdf107727_FrameBorder.odt";
+    mxComponent = loadFromDesktop(aURL, "com.sun.star.text.TextDocument", {});
+
+    // Export to RTF and reload
+    uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+    utl::TempFile aTempFile;
+    aTempFile.EnableKillingFile();
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OUString("Rich Text Format");
+    xStorable->storeToURL(aTempFile.GetURL(), 
aMediaDescriptor.getAsConstPropertyValueList());
+    mxComponent = loadFromDesktop(aTempFile.GetURL(), 
"com.sun.star.text.TextDocument", {});
+
+    // Get frame without border and inspect it.
+    uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xIndexAccess(xTextFramesSupplier->getTextFrames(),
+                                                         uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xFrame0(xIndexAccess->getByIndex(0), 
uno::UNO_QUERY);
+    auto aBorder = getProperty<table::BorderLine2>(xFrame0, "LeftBorder");
+    // fo:border="none" is not available via API, and aBorder.LineWidth has 
wrong value (why?).
+    sal_uInt32 nBorderWidth
+        = aBorder.OuterLineWidth + aBorder.InnerLineWidth + 
aBorder.LineDistance;
+    // Without patch it failed with Expected 0, Actual 26
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0), nBorderWidth);
+
+    // Get frame with left border and inspect it.
+    uno::Reference<beans::XPropertySet> xFrame1(xIndexAccess->getByIndex(1), 
uno::UNO_QUERY);
+    aBorder = getProperty<table::BorderLine2>(xFrame1, "LeftBorder");
+    // Without patch it failed with Expected 127, Actual 26. Default border 
width was used.
+    nBorderWidth = aBorder.OuterLineWidth + aBorder.InnerLineWidth + 
aBorder.LineDistance;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(127), nBorderWidth);
+    // Without patch it failed with Expected Color: R:0 G:0 B:255 A:0, Actual 
Color: R:0 G:0 B:0 A:0.
+    // Default border color was used.
+    CPPUNIT_ASSERT_EQUAL(Color(0x0000ff), Color(ColorTransparency, 
aBorder.Color));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx 
b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 8f9d48f05da2..657160b1ee52 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -3558,27 +3558,45 @@ void RtfAttributeOutput::FormatBox(const SvxBoxItem& 
rBox)
         const editeng::SvxBorderLine* pRight = 
rBox.GetLine(SvxBoxItemLine::RIGHT);
         const editeng::SvxBorderLine* pTop = rBox.GetLine(SvxBoxItemLine::TOP);
         const editeng::SvxBorderLine* pBottom = 
rBox.GetLine(SvxBoxItemLine::BOTTOM);
-        if (pLeft && pRight && pTop && pBottom && *pLeft == *pRight && *pLeft 
== *pTop
-            && *pLeft == *pBottom)
+
+        if (!pLeft && !pRight && !pBottom && !pTop)
         {
-            const Color& rColor = pTop->GetColor();
-            // We in fact need RGB to BGR, but the transformation is symmetric.
-            m_aFlyProperties.push_back(std::make_pair<OString, OString>(
-                "lineColor", OString::number(wwUtility::RGBToBGR(rColor))));
+            // fLine has default 'true', so need to write it out in case of no 
border.
+            m_aFlyProperties.push_back(std::make_pair<OString, 
OString>("fLine", "0"));
+            return;
+        }
 
-            if (pTop->GetBorderLineStyle() != SvxBorderLineStyle::NONE)
-            {
-                double const fConverted(editeng::ConvertBorderWidthToWord(
-                    pTop->GetBorderLineStyle(), pTop->GetWidth()));
-                sal_Int32 nWidth = o3tl::convert(fConverted, 
o3tl::Length::twip, o3tl::Length::emu);
-                m_aFlyProperties.push_back(
-                    std::make_pair<OString, OString>("lineWidth", 
OString::number(nWidth)));
-            }
-            else
-                // No border: no line.
-                m_aFlyProperties.push_back(std::make_pair<OString, 
OString>("fLine", "0"));
+        // RTF has the flags fTopLine, fBottomLine, fLeftLine and fRightLine 
to disable single border
+        // lines. But Word cannot disable single border lines. So we do not 
use them. In case of
+        // single border lines it is better to draw all four borders than 
drawing none. So we look
+        // whether a border line exists, which is effectively drawn.
+        const editeng::SvxBorderLine* pBorder = nullptr;
+        if (pTop && pTop->GetBorderLineStyle() != SvxBorderLineStyle::NONE)
+            pBorder = pTop;
+        else if (pBottom && pBottom->GetBorderLineStyle() != 
SvxBorderLineStyle::NONE)
+            pBorder = pBottom;
+        else if (pLeft && pLeft->GetBorderLineStyle() != 
SvxBorderLineStyle::NONE)
+            pBorder = pLeft;
+        else if (pRight && pRight->GetBorderLineStyle() != 
SvxBorderLineStyle::NONE)
+            pBorder = pRight;
+
+        if (!pBorder)
+        {
+            m_aFlyProperties.push_back(std::make_pair<OString, 
OString>("fLine", "0"));
+            return;
         }
 
+        const Color& rColor = pBorder->GetColor();
+        // We in fact need RGB to BGR, but the transformation is symmetric.
+        m_aFlyProperties.push_back(std::make_pair<OString, OString>(
+            "lineColor", OString::number(wwUtility::RGBToBGR(rColor))));
+
+        double const fConverted(
+            editeng::ConvertBorderWidthToWord(pBorder->GetBorderLineStyle(), 
pBorder->GetWidth()));
+        sal_Int32 nWidth = o3tl::convert(fConverted, o3tl::Length::twip, 
o3tl::Length::emu);
+        m_aFlyProperties.push_back(
+            std::make_pair<OString, OString>("lineWidth", 
OString::number(nWidth)));
+
         return;
     }
 

Reply via email to