diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2023-04-21 07:05:26 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-04-26 11:06:41 +0200 |
commit | 10b4b470238a92b5477f0a99ef65356032276163 (patch) | |
tree | ef4854d43fedebfa7866298f11952a588cac8ce8 /writerfilter | |
parent | e450cc5dcc84fb77ac8d655303c01ef795507be0 (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.mk | 1 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/rtftok/data/floating-table.rtf | 10 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/rtftok/rtfdispatchflag.cxx | 70 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdispatchflag.cxx | 97 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdispatchvalue.cxx | 66 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.hxx | 5 |
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 |