summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-04-21 08:22:21 +0200
committerMiklos Vajna <vmiklos@collabora.com>2023-04-21 09:02:33 +0200
commitf703ad86984bcc5e2271484cf45d36e1057b21ad (patch)
tree7a6ad5a5526d69b7b295afbcfdbbcd57d1f747cb
parent76e80a567fe41f885224d01c7dd22de7ee90606d (diff)
sw floatable: teach the RTF export about SwFormatFlySplit
Write \nobrkwrptbl unconditionally till we have a layout mode where floating/wrapped tables don't split/break. Change-Id: I0a19d034651a276dde8df391a5f1ca8ae39ddfed Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150739 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--include/svtools/rtfkeywd.hxx19
-rw-r--r--sw/qa/extras/rtfexport/rtfexport3.cxx60
-rw-r--r--sw/source/filter/ww8/rtfattributeoutput.cxx129
-rw-r--r--sw/source/filter/ww8/rtfattributeoutput.hxx1
-rw-r--r--sw/source/filter/ww8/rtfexport.cxx4
5 files changed, 209 insertions, 4 deletions
diff --git a/include/svtools/rtfkeywd.hxx b/include/svtools/rtfkeywd.hxx
index d1a4a59073b2..b4bac2af34cf 100644
--- a/include/svtools/rtfkeywd.hxx
+++ b/include/svtools/rtfkeywd.hxx
@@ -1221,5 +1221,24 @@
#define LO_STRING_SVTOOLS_RTF_GUTTERPRL "\\gutterprl"
#define LO_STRING_SVTOOLS_RTF_RTLGUTTER "\\rtlgutter"
#define LO_STRING_SVTOOLS_RTF_LBR "\\lbr"
+#define LO_STRING_SVTOOLS_RTF_TPVMRG "\\tpvmrg"
+#define LO_STRING_SVTOOLS_RTF_TPVPG "\\tpvpg"
+#define LO_STRING_SVTOOLS_RTF_TPVPARA "\\tpvpara"
+#define LO_STRING_SVTOOLS_RTF_NOBRKWRPTBL "\\nobrkwrptbl"
+#define LO_STRING_SVTOOLS_RTF_TPHCOL "\\tphcol"
+#define LO_STRING_SVTOOLS_RTF_TPHMRG "\\tphmrg"
+#define LO_STRING_SVTOOLS_RTF_TPHPG "\\tphpg"
+#define LO_STRING_SVTOOLS_RTF_TPOSXL "\\tposxl"
+#define LO_STRING_SVTOOLS_RTF_TPOSXC "\\tposxc"
+#define LO_STRING_SVTOOLS_RTF_TPOSXR "\\tposxr"
+#define LO_STRING_SVTOOLS_RTF_TPOSX "\\tposx"
+#define LO_STRING_SVTOOLS_RTF_TPOSYT "\\tposyt"
+#define LO_STRING_SVTOOLS_RTF_TPOSYC "\\tposyc"
+#define LO_STRING_SVTOOLS_RTF_TPOSYB "\\tposyb"
+#define LO_STRING_SVTOOLS_RTF_TPOSY "\\tposy"
+#define LO_STRING_SVTOOLS_RTF_TDFRMTXTLEFT "\\tdfrmtxtLeft"
+#define LO_STRING_SVTOOLS_RTF_TDFRMTXTRIGHT "\\tdfrmtxtRight"
+#define LO_STRING_SVTOOLS_RTF_TDFRMTXTTOP "\\tdfrmtxtTop"
+#define LO_STRING_SVTOOLS_RTF_TDFRMTXTBOTTOM "\\tdfrmtxtBottom"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/rtfexport/rtfexport3.cxx b/sw/qa/extras/rtfexport/rtfexport3.cxx
index 83d1743e05d2..2b45ca61f33e 100644
--- a/sw/qa/extras/rtfexport/rtfexport3.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport3.cxx
@@ -21,6 +21,7 @@
#include <comphelper/sequenceashashmap.hxx>
#include <tools/UnitConversion.hxx>
+#include <comphelper/propertyvalue.hxx>
#include <unotxdoc.hxx>
#include <docsh.hxx>
@@ -559,6 +560,65 @@ DECLARE_RTFEXPORT_TEST(testTdf152784_1, "tdf152784_1.rtf")
CPPUNIT_ASSERT(getProperty<OUString>(xPara, "NumberingStyleName").isEmpty());
}
+CPPUNIT_TEST_FIXTURE(Test, testFloatingTableExport)
+{
+ // Given a document with a floating table:
+ mxComponent = loadFromDesktop("private:factory/swriter");
+ // Insert a table:
+ uno::Sequence<beans::PropertyValue> aArgs = {
+ comphelper::makePropertyValue("Rows", static_cast<sal_Int32>(1)),
+ comphelper::makePropertyValue("Columns", static_cast<sal_Int32>(1)),
+ };
+ dispatchCommand(mxComponent, ".uno:InsertTable", aArgs);
+ // Select it:
+ dispatchCommand(mxComponent, ".uno:SelectAll", {});
+ // Wrap in a fly:
+ aArgs = {
+ comphelper::makePropertyValue("AnchorType", static_cast<sal_uInt16>(0)),
+ };
+ dispatchCommand(mxComponent, ".uno:InsertFrame", aArgs);
+ // Mark it as a floating table:
+ uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xFrame(
+ xTextFramesSupplier->getTextFrames()->getByName("Frame1"), uno::UNO_QUERY);
+ xFrame->setPropertyValue("IsSplitAllowed", uno::Any(true));
+ // Originally 10, 30 & 40 twips.
+ xFrame->setPropertyValue("VertOrientPosition", uno::Any(static_cast<sal_Int32>(18)));
+ xFrame->setPropertyValue("LeftMargin", uno::Any(static_cast<sal_Int32>(53)));
+ xFrame->setPropertyValue("RightMargin", uno::Any(static_cast<sal_Int32>(71)));
+
+ // When saving to RTF:
+ reload(mpFilter, "floating-table.rtf");
+
+ // Then make sure the floating table is there & has the expected properties:
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ xFrame.set(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ bool bIsSplitAllowed{};
+ xFrame->getPropertyValue("IsSplitAllowed") >>= bIsSplitAllowed;
+ // Without the accompanying fix in place, this test would have failed, the table was not
+ // multi-page.
+ CPPUNIT_ASSERT(bIsSplitAllowed);
+ sal_Int16 nVertOrientRelation{};
+ xFrame->getPropertyValue("VertOrientRelation") >>= nVertOrientRelation;
+ CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME, nVertOrientRelation);
+ sal_Int16 nHoriOrientRelation{};
+ xFrame->getPropertyValue("HoriOrientRelation") >>= nHoriOrientRelation;
+ CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME, nHoriOrientRelation);
+ sal_Int32 nVertOrientPosition{};
+ xFrame->getPropertyValue("VertOrientPosition") >>= nVertOrientPosition;
+ sal_Int32 nExpected = 18;
+ CPPUNIT_ASSERT_EQUAL(nExpected, nVertOrientPosition);
+ sal_Int32 nLeftMargin{};
+ xFrame->getPropertyValue("LeftMargin") >>= nLeftMargin;
+ nExpected = 53;
+ CPPUNIT_ASSERT_EQUAL(nExpected, nLeftMargin);
+ sal_Int32 nRightMargin{};
+ xFrame->getPropertyValue("RightMargin") >>= nRightMargin;
+ nExpected = 71;
+ CPPUNIT_ASSERT_EQUAL(nExpected, nRightMargin);
+}
+
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 4e5a583264dd..0d59c8dfae4e 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -91,6 +91,7 @@
#include <svl/grabbagitem.hxx>
#include <frmatr.hxx>
#include <swtable.hxx>
+#include <formatflysplit.hxx>
#include "rtfexport.hxx"
using namespace ::com::sun::star;
@@ -676,6 +677,108 @@ void RtfAttributeOutput::TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t /*pT
/* noop */
}
+void RtfAttributeOutput::TablePositioning(SwFrameFormat* pFlyFormat)
+{
+ if (!pFlyFormat || !pFlyFormat->GetFlySplit().GetValue())
+ {
+ return;
+ }
+
+ switch (pFlyFormat->GetVertOrient().GetRelationOrient())
+ {
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ // relative to margin
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPVMRG);
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ // relative to page
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPVPG);
+ break;
+ default:
+ // text::RelOrientation::FRAME
+ // relative to text
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPVPARA);
+ break;
+ }
+
+ switch (pFlyFormat->GetHoriOrient().GetRelationOrient())
+ {
+ case text::RelOrientation::FRAME:
+ // relative to column
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPHCOL);
+ break;
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ // relative to margin
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPHMRG);
+ break;
+ default:
+ // text::RelOrientation::PAGE_FRAME
+ // relative to page
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPHPG);
+ break;
+ }
+
+ // Similar to RtfAttributeOutput::FormatHorizOrientation(), but for tables.
+ switch (pFlyFormat->GetHoriOrient().GetHoriOrient())
+ {
+ case text::HoriOrientation::LEFT:
+ // left
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSXL);
+ break;
+ case text::HoriOrientation::CENTER:
+ // centered
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSXC);
+ break;
+ case text::HoriOrientation::RIGHT:
+ // right
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSXR);
+ break;
+ default:
+ SwTwips nTPosX = pFlyFormat->GetHoriOrient().GetPos();
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSX);
+ m_aRowDefs.append(static_cast<sal_Int32>(nTPosX));
+ break;
+ }
+
+ // Similar to RtfAttributeOutput::FormatVertOrientation(), but for tables.
+ switch (pFlyFormat->GetVertOrient().GetVertOrient())
+ {
+ case text::VertOrientation::TOP:
+ // up
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSYT);
+ break;
+ case text::VertOrientation::CENTER:
+ // centered
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSYC);
+ break;
+ case text::VertOrientation::BOTTOM:
+ // down
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSYB);
+ break;
+ default:
+ SwTwips nTPosY = pFlyFormat->GetVertOrient().GetPos();
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TPOSY);
+ m_aRowDefs.append(static_cast<sal_Int32>(nTPosY));
+ break;
+ }
+
+ // Similar to RtfAttributeOutput::FormatULSpace(), but for tables.
+ sal_uInt16 nTdfrmtxtTop = pFlyFormat->GetULSpace().GetUpper();
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTTOP);
+ m_aRowDefs.append(static_cast<sal_Int32>(nTdfrmtxtTop));
+ sal_uInt16 nTdfrmtxtBottom = pFlyFormat->GetULSpace().GetLower();
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTBOTTOM);
+ m_aRowDefs.append(static_cast<sal_Int32>(nTdfrmtxtBottom));
+
+ // Similar to RtfAttributeOutput::FormatLRSpace(), but for tables.
+ sal_uInt16 nTdfrmtxtLeft = pFlyFormat->GetLRSpace().GetLeft();
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTLEFT);
+ m_aRowDefs.append(static_cast<sal_Int32>(nTdfrmtxtLeft));
+ sal_uInt16 nTdfrmtxtRight = pFlyFormat->GetLRSpace().GetRight();
+ m_aRowDefs.append(LO_STRING_SVTOOLS_RTF_TDFRMTXTRIGHT);
+ m_aRowDefs.append(static_cast<sal_Int32>(nTdfrmtxtRight));
+}
+
void RtfAttributeOutput::TableDefinition(
ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
{
@@ -690,6 +793,9 @@ void RtfAttributeOutput::TableDefinition(
TableHeight(pTableTextNodeInfoInner);
TableCanSplit(pTableTextNodeInfoInner);
+ // Write table positioning properties in case this is a floating table.
+ TablePositioning(pTable->GetTableNode()->GetFlyFormat());
+
// Cell margins
const SvxBoxItem& rBox = pFormat->GetBox();
static const SvxBoxItemLine aBorders[] = { SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT,
@@ -1095,7 +1201,9 @@ void RtfAttributeOutput::EndTableRow()
m_aAfterRuns.append(m_aTables.back());
m_aTables.pop_back();
}
- m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ROW OOO_STRING_SVTOOLS_RTF_PARD);
+ // Make sure that the first word of the next paragraph is not merged with the last control
+ // word of this table row, happens with floating tables.
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ROW OOO_STRING_SVTOOLS_RTF_PARD " ");
}
m_bTableRowEnded = true;
}
@@ -2037,6 +2145,22 @@ public:
void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame& rFrame, const Point& /*rNdTopLeft*/)
{
+ const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
+ if (rFrameFormat.GetFlySplit().GetValue())
+ {
+ // The frame can split: this was originally from a floating table, write it back as
+ // such.
+ SaveRunState aState(*this);
+ const SwNodeIndex* pNodeIndex = rFrameFormat.GetContent().GetContentIdx();
+ SwNodeOffset nStt = pNodeIndex ? pNodeIndex->GetIndex() + 1 : SwNodeOffset(0);
+ SwNodeOffset nEnd
+ = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : SwNodeOffset(0);
+ m_rExport.SaveData(nStt, nEnd);
+ GetExport().WriteText();
+ m_rExport.RestoreData();
+ return;
+ }
+
const SwNode* pNode = rFrame.GetContent();
const SwGrfNode* pGrfNode = pNode ? pNode->GetGrfNode() : nullptr;
@@ -2083,7 +2207,6 @@ void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame& rFrame, const Poi
m_rExport.SetRTFFlySyntax(false);
m_pFlyFrameSize = nullptr;
- const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
lcl_TextFrameShadow(m_aFlyProperties, rFrameFormat);
lcl_TextFrameRelativeSize(m_aFlyProperties, rFrameFormat);
@@ -2145,7 +2268,6 @@ void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame& rFrame, const Poi
break;
case ww8::Frame::eFormControl:
{
- const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
const SdrObject* pObject = rFrameFormat.FindRealSdrObject();
m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
@@ -2377,7 +2499,6 @@ void RtfAttributeOutput::OutputFlyFrame_Impl(const ww8::Frame& rFrame, const Poi
break;
case ww8::Frame::eOle:
{
- const SwFrameFormat& rFrameFormat = rFrame.GetFrameFormat();
const SdrObject* pSdrObj = rFrameFormat.FindRealSdrObject();
if (pSdrObj)
{
diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx
index fdd5ed09d3bc..6e5a3c77cd2c 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.hxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -125,6 +125,7 @@ public:
void TableInfoCell(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override;
void TableInfoRow(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override;
void TableDefinition(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override;
+ void TablePositioning(SwFrameFormat* pFlyFormat);
void
TableDefaultBorders(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override;
void TableBackgrounds(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner) override;
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
index ccde1138c76c..4b78a464c7c5 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -856,6 +856,10 @@ ErrCode RtfExport::ExportDocument_Impl()
// enable form field shading
Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FORMSHADE);
+ // Enable breaking wrapped tables across pages: the "no" in the control word's name is
+ // confusing.
+ Strm().WriteOString(LO_STRING_SVTOOLS_RTF_NOBRKWRPTBL);
+
// size and empty margins of the page
if (m_rDoc.GetPageDescCnt())
{