summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-04-21 07:05:26 +0200
committerMiklos Vajna <vmiklos@collabora.com>2023-04-26 11:06:41 +0200
commit10b4b470238a92b5477f0a99ef65356032276163 (patch)
treeef4854d43fedebfa7866298f11952a588cac8ce8 /writerfilter
parente450cc5dcc84fb77ac8d655303c01ef795507be0 (diff)
sw floatable: teach the RTF import about SwFormatFlySplit
- if the document has no \nobrkwrptbl, then ignore all floating table control word for now - map the rest of the RTF control words to OOXML attributes under the NS_ooxml::LN_CT_TblPrBase_tblpPr sprm: - \tpv{para,mrg,pg} -> NS_ooxml::LN_CT_TblPPr_vertAnchor - \tph{col,mrg,pg} -> NS_ooxml::LN_CT_TblPPr_horzAnchor - \tposy -> NS_ooxml::LN_CT_TblPPr_tblpY - \tposy{c,b} -> NS_ooxml::LN_CT_TblPPr_tblpYSpec - \tposx -> NS_ooxml::LN_CT_TblPPr_tblpX - \tposx{c,r} -> NS_ooxml::LN_CT_TblPPr_tblpXSpec - \tdfrmtxtLeft -> NS_ooxml::LN_CT_TblPPr_leftFromText - \tdfrmtxtRight -> NS_ooxml::LN_CT_TblPPr_rightFromText - \tdfrmtxtTop -> NS_ooxml::LN_CT_TblPPr_topFromText - \tdfrmtxtBottom -> NS_ooxml::LN_CT_TblPPr_bottomFromText (cherry picked from commit 05425f73bfa41d3f7591461e2ad0beb4fafc39b4) Change-Id: I0b30d0eba8c1b7b6d3497334c958146717d06552 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150900 Tested-by: Miklos Vajna <vmiklos@collabora.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/CppunitTest_writerfilter_rtftok.mk1
-rw-r--r--writerfilter/qa/cppunittests/rtftok/data/floating-table.rtf10
-rw-r--r--writerfilter/qa/cppunittests/rtftok/rtfdispatchflag.cxx70
-rw-r--r--writerfilter/source/rtftok/rtfdispatchflag.cxx97
-rw-r--r--writerfilter/source/rtftok/rtfdispatchvalue.cxx66
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx5
6 files changed, 249 insertions, 0 deletions
diff --git a/writerfilter/CppunitTest_writerfilter_rtftok.mk b/writerfilter/CppunitTest_writerfilter_rtftok.mk
index 990aa6596d3d..2c91cbb8cb2f 100644
--- a/writerfilter/CppunitTest_writerfilter_rtftok.mk
+++ b/writerfilter/CppunitTest_writerfilter_rtftok.mk
@@ -16,6 +16,7 @@ $(eval $(call gb_CppunitTest_use_externals,writerfilter_rtftok,\
))
$(eval $(call gb_CppunitTest_add_exception_objects,writerfilter_rtftok, \
+ writerfilter/qa/cppunittests/rtftok/rtfdispatchflag \
writerfilter/qa/cppunittests/rtftok/rtfdispatchsymbol \
writerfilter/qa/cppunittests/rtftok/rtfdispatchvalue \
writerfilter/qa/cppunittests/rtftok/rtfdocumentimpl \
diff --git a/writerfilter/qa/cppunittests/rtftok/data/floating-table.rtf b/writerfilter/qa/cppunittests/rtftok/data/floating-table.rtf
new file mode 100644
index 000000000000..b88664139070
--- /dev/null
+++ b/writerfilter/qa/cppunittests/rtftok/data/floating-table.rtf
@@ -0,0 +1,10 @@
+{\rtf1
+\paperw12240\paperh6203\margl1440\margr1440\margt1440\margb1440\nobrkwrptbl
+\pard\plain First paragraph\par
+\pard\plain\intbl A1\cell
+\pard\plain\trowd\trrh1812\tpvpara\tphcol\tposy10\tposx20\tdfrmtxtLeft30\tdfrmtxtRight40\cellx3828\row
+\pard\plain\intbl A2\cell
+\pard\plain\trowd\trrh1812\tpvpara\tphcol\tposy10\tposx20\tdfrmtxtLeft30\tdfrmtxtRight40\cellx3828\row
+\pard\plain Second paragraph.
+\par
+}
diff --git a/writerfilter/qa/cppunittests/rtftok/rtfdispatchflag.cxx b/writerfilter/qa/cppunittests/rtftok/rtfdispatchflag.cxx
new file mode 100644
index 000000000000..810dc750d7d7
--- /dev/null
+++ b/writerfilter/qa/cppunittests/rtftok/rtfdispatchflag.cxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <test/unoapi_test.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+/// Tests for writerfilter/source/rtftok/rtfdispatchflag.cxx.
+class Test : public UnoApiTest
+{
+public:
+ Test()
+ : UnoApiTest("/writerfilter/qa/cppunittests/rtftok/data/")
+ {
+ }
+};
+
+CPPUNIT_TEST_FIXTURE(Test, testFloatingTable)
+{
+ // Given a document with a floating table, when importing that document:
+ loadFromURL(u"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();
+ // Without the accompanying fix in place, this test would have failed with:
+ // An uncaught exception of type com.sun.star.lang.IndexOutOfBoundsException
+ // i.e. the table was not floating / was not in a fly frame.
+ uno::Reference<beans::XPropertySet> xFrame(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ bool bIsSplitAllowed{};
+ xFrame->getPropertyValue("IsSplitAllowed") >>= bIsSplitAllowed;
+ 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 = o3tl::convert(10, o3tl::Length::twip, o3tl::Length::mm100);
+ CPPUNIT_ASSERT_EQUAL(nExpected, nVertOrientPosition);
+ sal_Int32 nHoriOrientPosition{};
+ xFrame->getPropertyValue("HoriOrientPosition") >>= nHoriOrientPosition;
+ nExpected = o3tl::convert(20, o3tl::Length::twip, o3tl::Length::mm100);
+ CPPUNIT_ASSERT_EQUAL(nExpected, nHoriOrientPosition);
+ sal_Int32 nLeftMargin{};
+ xFrame->getPropertyValue("LeftMargin") >>= nLeftMargin;
+ nExpected = o3tl::convert(30, o3tl::Length::twip, o3tl::Length::mm100);
+ CPPUNIT_ASSERT_EQUAL(nExpected, nLeftMargin);
+ sal_Int32 nRightMargin{};
+ xFrame->getPropertyValue("RightMargin") >>= nRightMargin;
+ nExpected = o3tl::convert(40, o3tl::Length::twip, o3tl::Length::mm100);
+ CPPUNIT_ASSERT_EQUAL(nExpected, nRightMargin);
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/rtftok/rtfdispatchflag.cxx b/writerfilter/source/rtftok/rtfdispatchflag.cxx
index 0ef4f21729d6..bc3c3037e16d 100644
--- a/writerfilter/source/rtftok/rtfdispatchflag.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchflag.cxx
@@ -32,6 +32,93 @@ using namespace com::sun::star;
namespace writerfilter::rtftok
{
+bool RTFDocumentImpl::dispatchFloatingTableFlag(RTFKeyword nKeyword)
+{
+ if (!m_bBreakWrappedTables)
+ {
+ return false;
+ }
+
+ // Positioned Wrapped Tables
+ OUString aParam;
+ switch (nKeyword)
+ {
+ case RTFKeyword::TPVPARA:
+ aParam = "text";
+ break;
+ case RTFKeyword::TPVMRG:
+ aParam = "margin";
+ break;
+ case RTFKeyword::TPVPG:
+ aParam = "page";
+ break;
+ default:
+ break;
+ }
+ if (!aParam.isEmpty())
+ {
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_vertAnchor, new RTFValue(aParam));
+ return true;
+ }
+ switch (nKeyword)
+ {
+ case RTFKeyword::TPHCOL:
+ aParam = "text";
+ break;
+ case RTFKeyword::TPHMRG:
+ aParam = "margin";
+ break;
+ case RTFKeyword::TPHPG:
+ aParam = "page";
+ break;
+ default:
+ break;
+ }
+ if (!aParam.isEmpty())
+ {
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_horzAnchor, new RTFValue(aParam));
+ return true;
+ }
+ switch (nKeyword)
+ {
+ case RTFKeyword::TPOSYC:
+ aParam = "center";
+ break;
+ case RTFKeyword::TPOSYB:
+ aParam = "bottom";
+ break;
+ default:
+ break;
+ }
+ if (!aParam.isEmpty())
+ {
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_tblpYSpec, new RTFValue(aParam));
+ return true;
+ }
+ switch (nKeyword)
+ {
+ case RTFKeyword::TPOSXC:
+ aParam = "center";
+ break;
+ case RTFKeyword::TPOSXR:
+ aParam = "right";
+ break;
+ default:
+ break;
+ }
+ if (!aParam.isEmpty())
+ {
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_tblpXSpec, new RTFValue(aParam));
+ return true;
+ }
+
+ return false;
+}
+
RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
{
setNeedSect(true);
@@ -442,6 +529,11 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
return RTFError::OK;
}
+ if (dispatchFloatingTableFlag(nKeyword))
+ {
+ return RTFError::OK;
+ }
+
switch (nKeyword)
{
case RTFKeyword::FNIL:
@@ -1243,6 +1335,11 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
m_aStates.top().setFieldLocked(true);
}
break;
+ case RTFKeyword::NOBRKWRPTBL:
+ {
+ m_bBreakWrappedTables = true;
+ }
+ break;
default:
{
SAL_INFO("writerfilter", "TODO handle flag '" << keywordToString(nKeyword) << "'");
diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
index a56d8e00d819..f580ec69c5e9 100644
--- a/writerfilter/source/rtftok/rtfdispatchvalue.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
@@ -1823,6 +1823,72 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
}
}
break;
+ case RTFKeyword::TPOSY:
+ {
+ if (!m_bBreakWrappedTables)
+ {
+ break;
+ }
+
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_tblpY, new RTFValue(nParam));
+ }
+ break;
+ case RTFKeyword::TPOSX:
+ {
+ if (!m_bBreakWrappedTables)
+ {
+ break;
+ }
+
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_tblpX, new RTFValue(nParam));
+ }
+ break;
+ case RTFKeyword::TDFRMTXTLEFT:
+ {
+ if (!m_bBreakWrappedTables)
+ {
+ break;
+ }
+
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_leftFromText, new RTFValue(nParam));
+ }
+ break;
+ case RTFKeyword::TDFRMTXTRIGHT:
+ {
+ if (!m_bBreakWrappedTables)
+ {
+ break;
+ }
+
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_rightFromText, new RTFValue(nParam));
+ }
+ break;
+ case RTFKeyword::TDFRMTXTTOP:
+ {
+ if (!m_bBreakWrappedTables)
+ {
+ break;
+ }
+
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_topFromText, new RTFValue(nParam));
+ }
+ break;
+ case RTFKeyword::TDFRMTXTBOTTOM:
+ {
+ if (!m_bBreakWrappedTables)
+ {
+ break;
+ }
+
+ putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblpPr,
+ NS_ooxml::LN_CT_TblPPr_bottomFromText, new RTFValue(nParam));
+ }
+ break;
default:
{
SAL_INFO("writerfilter", "TODO handle value '" << keywordToString(nKeyword) << "'");
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 71ecd06c8cd8..bf1ff2c30611 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -701,6 +701,8 @@ public:
// RTFListener
RTFError dispatchDestination(RTFKeyword nKeyword) override;
RTFError dispatchFlag(RTFKeyword nKeyword) override;
+ /// Dispatches flags related to Positioned Wrapped Tables.
+ bool dispatchFloatingTableFlag(RTFKeyword nKeyword);
RTFError dispatchSymbol(RTFKeyword nKeyword) override;
RTFError dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam) override;
RTFError dispatchValue(RTFKeyword nKeyword, int nParam) override;
@@ -989,6 +991,9 @@ private:
/// Are we after a \cell, but before a \row?
bool m_bAfterCellBeforeRow;
+
+ /// Floating tables are single-page by default.
+ bool m_bBreakWrappedTables = false;
};
} // namespace writerfilter::rtftok