tdf#129631 writerfilter,sw: RTF import of invalid border...
... and export of border on paragraph that clears the border from the
paragraph style.
The import problem is that a lone \brdrcf17 without any preceding
keyword about which border it belongs to (as required by the EBNF in the
RTF spec) is apparently handled by Word as overriding/clearing all
paragraph borders that may be inherited from the paragraph style.
The export problem is that a null SvxBorderLine isn't exported at all,
but there needs to be a \brdrnone to override the definition from the
style.
There was also an API problem that the null SvxBorderLine is wrongly
converted to a table::BorderLine2 with LineStyle SOLID.
Change-Id: I5fa3857de2ef843f5194e12dd0c3e57bcf1ca52b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138089
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx
index c4c79dc..35e1be7 100644
--- a/editeng/source/items/frmitems.cxx
+++ b/editeng/source/items/frmitems.cxx
@@ -1387,7 +1387,10 @@ table::BorderLine2 SvxBoxItem::SvxLineToLine(const SvxBorderLine* pLine, bool bC
aLine.LineWidth = sal_uInt32( bConvert ? convertTwipToMm100( pLine->GetWidth( ) ) : pLine->GetWidth( ) );
}
else
{
aLine.Color = aLine.InnerLineWidth = aLine.OuterLineWidth = aLine.LineDistance = 0;
aLine.LineStyle = table::BorderLineStyle::NONE; // 0 is SOLID!
}
return aLine;
}
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index 2511096..ad65d88 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -1111,7 +1111,7 @@ DECLARE_ODFEXPORT_TEST(testCharacterBorder, "charborder.odt")
table::BorderLine2(0xFF3333,0,37,0,14,37), // Top (fine dashed line)
table::BorderLine2(0x99FF66,26,26,53,11,106), // Bottom
table::BorderLine2(0x6666FF,9,26,9,12,71), // Left
table::BorderLine2(0,0,0,0,0,0) // Right
table::BorderLine2(0,0,0,0,table::BorderLineStyle::NONE,0) // Right
};
sal_Int32 aDistances[4] = { 400 /*Top*/, 300 /*Bottom*/, 250 /*Left*/, 0 /*Right*/ };
diff --git a/sw/qa/extras/rtfexport/data/tdf129631_lostBorders3.rtf b/sw/qa/extras/rtfexport/data/tdf129631_lostBorders3.rtf
new file mode 100644
index 0000000..dba7db7
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf129631_lostBorders3.rtf
@@ -0,0 +1,27 @@
{\rtf1\ansi\deff4\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq0\fcharset0 Times New Roman;}{\f5\fnil\fprq2\fcharset0 DejaVu Sans;}}
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red6\green154\blue46;}
{\stylesheet{\s0\snext0\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\ltrpar\hyphpar0\aspalpha\cf0\loch\f3\fs24\lang255\kerning1 Normal;}
{\*\cs15\snext15 CharShadow;}
{\*\cs16\sbasedon15\snext16 CharShadow-removed;}
{\s17\sbasedon0\snext18\dbch\af5\langfe2052\dbch\af4\afs28\alang1025\ql\widctlpar\sb240\sa120\keepn\ltrpar\cf0\loch\f4\fs28\lang255\kerning1 Heading;}
{\s18\sbasedon0\snext18\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\sl276\slmult1\ql\widctlpar\sb0\sa140\ltrpar\cf0\loch\f3\fs24\lang255\kerning1 Text Body;}
{\s19\sbasedon18\snext19\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\sl276\slmult1\ql\widctlpar\sb0\sa140\ltrpar\cf0\loch\f4\fs24\lang255\kerning1 List;}
{\s20\sbasedon0\snext20\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ai\ql\widctlpar\sb120\sa120\noline\ltrpar\cf0\loch\f4\fs24\lang255\i\kerning1 Caption;}
{\s21\sbasedon0\snext21\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\noline\ltrpar\cf0\loch\f4\fs24\lang255\kerning1 Index;}
{\s22\sbasedon0\snext22\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\brdrt\brdrs\brdrw50\brdrcf1\brsp0\brdrl\brdrs\brdrw50\brdrcf1\brsp0\brdrb\brdrs\brdrw50\brdrcf1\brsp20\brdrr\brdrs\brdrw50\brdrcf1\brsp20\ltrpar\cf0\loch\f3\fs48\lang255\i\b\kerning1 Border;}
{\s23\sbasedon0\snext23\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\sb0\sa60\noline\ltrpar\cf0\loch\f3\fs24\lang255\kerning1 Sender;}
}{\*\generator LibreOfficeDev/6.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/c71d886120998884fdd16a862826f59883d9a114}{\info{\creatim\yr2019\mo12\dy21\hr9\min10}{\revtim\yr2019\mo12\dy26\hr11\min50}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709
\viewscale140
{\*\pgdsctbl
{\pgdsc0\pgdscuse451\lndscpsxn\pgwsxn8391\pghsxn5953\marglsxn1134\margrsxn1134\margtsxn992\margbsxn992\pgdscnxt0 Default Style;}}
\formshade{\*\pgdscno0}\landscape\paperh5953\paperw8391\margl1134\margr1134\margt992\margb992\sectd\sbknone\sectunlocked1\lndscpsxn\pgndec\pgwsxn8391\pghsxn5953\marglsxn1134\margrsxn1134\margtsxn992\margbsxn992\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc\htmautsp
{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\ltrpar\hyphpar0\aspalpha\cf0\loch\f3\fs24\lang255\kerning1{\loch
Paragraph border are NOT inherited from styles if partially re-defined directly.}
\par \pard\plain \s22\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\cf0\loch\f3\fs48\lang255\i\b\kerning1\brdrcf17{\loch
Here colored green by direct formating, but no borders defined.}
\par \pard\plain \s0\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\ltrpar\hyphpar0\aspalpha\cf0\loch\f3\fs24\lang255\kerning1\loch
\par \pard\plain \s22\dbch\af5\langfe2052\dbch\af4\afs24\alang1025\ql\widctlpar\brdrt\brdrs\brdrw50\brdrcf1\brsp0\brdrl\brdrs\brdrw50\brdrcf1\brsp0\brdrb\brdrs\brdrw50\brdrcf1\brsp20\brdrr\brdrs\brdrw50\brdrcf1\brsp20\ltrpar\cf0\loch\f3\fs48\lang255\i\b\kerning1{\loch
End of test}
\par }
diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx b/sw/qa/extras/rtfexport/rtfexport4.cxx
index a8bf53f..03fb7c2 100644
--- a/sw/qa/extras/rtfexport/rtfexport4.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport4.cxx
@@ -123,6 +123,57 @@ DECLARE_RTFEXPORT_TEST(test150269, "hidden-linebreaks.rtf")
CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xRun, "CharHidden"));
}
DECLARE_RTFEXPORT_TEST(test129758, "tdf129631_lostBorders3.rtf")
{
uno::Reference<container::XNameAccess> xStyles(getStyles("ParagraphStyles"));
uno::Reference<beans::XPropertySet> xStyle(xStyles->getByName("Border"), uno::UNO_QUERY);
// style has borders
table::BorderLine2 border;
border = getProperty<table::BorderLine2>(xStyle, "RightBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
border = getProperty<table::BorderLine2>(xStyle, "LeftBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
border = getProperty<table::BorderLine2>(xStyle, "TopBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
border = getProperty<table::BorderLine2>(xStyle, "BottomBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
// style applied
uno::Reference<beans::XPropertySet> xPara2(getParagraph(2), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString("Border"), getProperty<OUString>(xPara2, "ParaStyleName"));
// but no borders
border = getProperty<table::BorderLine2>(xPara2, "RightBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::NONE, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), border.LineWidth);
border = getProperty<table::BorderLine2>(xPara2, "LeftBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::NONE, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), border.LineWidth);
border = getProperty<table::BorderLine2>(xPara2, "TopBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::NONE, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), border.LineWidth);
border = getProperty<table::BorderLine2>(xPara2, "BottomBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::NONE, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), border.LineWidth);
// last paragraph: style applied, no override
uno::Reference<beans::XPropertySet> xPara4(getParagraph(4), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString("Border"), getProperty<OUString>(xPara4, "ParaStyleName"));
border = getProperty<table::BorderLine2>(xPara4, "RightBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
border = getProperty<table::BorderLine2>(xPara4, "LeftBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
border = getProperty<table::BorderLine2>(xPara4, "TopBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
border = getProperty<table::BorderLine2>(xPara4, "BottomBorder");
CPPUNIT_ASSERT_EQUAL(table::BorderLineStyle::SOLID, border.LineStyle);
CPPUNIT_ASSERT_EQUAL(sal_uInt32(88), border.LineWidth);
}
DECLARE_RTFEXPORT_TEST(testAnchoredAtSamePosition, "anchor.fodt")
{
SwXTextDocument* const pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 9576ea8..a7f7086 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -188,6 +188,11 @@ static OString OutTBLBorderLine(RtfExport const& rExport, const editeng::SvxBord
aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRCF);
aRet.append(static_cast<sal_Int32>(rExport.GetColor(pLine->GetColor())));
}
else // tdf#129758 "no border" may be needed to override style
{
aRet.append(pStr);
aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRNONE);
}
return aRet.makeStringAndClear();
}
@@ -197,8 +202,11 @@ static OString OutBorderLine(RtfExport const& rExport, const editeng::SvxBorderL
{
OStringBuffer aRet;
aRet.append(OutTBLBorderLine(rExport, pLine, pStr));
aRet.append(OOO_STRING_SVTOOLS_RTF_BRSP);
aRet.append(static_cast<sal_Int32>(nDist));
if (pLine)
{
aRet.append(OOO_STRING_SVTOOLS_RTF_BRSP);
aRet.append(static_cast<sal_Int32>(nDist));
}
if (eShadowLocation == SvxShadowLocation::BottomRight)
aRet.append(LO_STRING_SVTOOLS_RTF_BRDRSH);
return aRet.makeStringAndClear();
@@ -3673,11 +3681,9 @@ void RtfAttributeOutput::FormatBox(const SvxBoxItem& rBox)
const char** pBrdNms = aBorderNames;
for (int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
{
if (const editeng::SvxBorderLine* pLn = rBox.GetLine(*pBrd))
{
m_aSectionBreaks.append(OutBorderLine(m_rExport, pLn, *pBrdNms,
rBox.GetDistance(*pBrd), eShadowLocation));
}
editeng::SvxBorderLine const* const pLn = rBox.GetLine(*pBrd);
m_aSectionBreaks.append(
OutBorderLine(m_rExport, pLn, *pBrdNms, rBox.GetDistance(*pBrd), eShadowLocation));
}
}
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 840a6bb..b3181e6 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -186,6 +186,21 @@ void putBorderProperty(RTFStack& aStates, Id nId, const RTFValue::Pointer_t& pVa
else if (aStates.top().getBorderState() == RTFBorderState::PAGE)
pAttributes = &getLastAttributes(aStates.top().getSectionSprms(),
NS_ooxml::LN_EG_SectPrContents_pgBorders);
else if (aStates.top().getBorderState() == RTFBorderState::NONE)
{
// this is invalid, but Word apparently clears or overrides all paragraph borders now
for (int i = 0; i < 4; ++i)
{
auto const nBorder = getParagraphBorder(i);
RTFSprms aAttributes;
RTFSprms aSprms;
aAttributes.set(NS_ooxml::LN_CT_Border_val,
new RTFValue(NS_ooxml::LN_Value_ST_Border_none));
putNestedSprm(aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PrBase_pBdr, nBorder,
new RTFValue(aAttributes, aSprms), RTFOverwrite::YES);
}
}
if (pAttributes)
pAttributes->set(nId, pValue);
}