sw/qa/extras/ooxmlexport/data/clearing-break.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 13 +++++++ sw/source/filter/ww8/attributeoutputbase.hxx | 3 + sw/source/filter/ww8/docxattributeoutput.cxx | 36 ++++++++++++++++++++++ sw/source/filter/ww8/docxattributeoutput.hxx | 8 ++++ sw/source/filter/ww8/rtfattributeoutput.cxx | 2 + sw/source/filter/ww8/rtfattributeoutput.hxx | 2 + sw/source/filter/ww8/ww8atr.cxx | 5 +++ sw/source/filter/ww8/ww8attributeoutput.hxx | 2 + 9 files changed, 71 insertions(+)
New commits: commit 280ab11ee40c95d2513e6f23ec5b08a083ecc1c5 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Mar 9 08:32:24 2022 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Mar 9 09:30:13 2022 +0100 sw clearing breaks: add DOCX export Need to do this in two passes, because a clearing line break is a text attribute, but the DOCX markup is not a run property, so can only write it once the run properties are finished. Change-Id: I74e94dbd02ca4e6ceee0439c5eafd3c3bbe2264b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131231 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/extras/ooxmlexport/data/clearing-break.docx b/sw/qa/extras/ooxmlexport/data/clearing-break.docx new file mode 100644 index 000000000000..453a4c2b83d1 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/clearing-break.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 5de93edd3226..7905091de82f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -75,6 +75,19 @@ CPPUNIT_TEST_FIXTURE(Test, testParaStyleNumLevel) assertXPath(pXmlDoc, "/w:styles/w:style[@w:styleId='Mystyle']/w:pPr/w:numPr/w:ilvl", "val", "1"); } +CPPUNIT_TEST_FIXTURE(Test, testClearingBreak) +{ + // Given a document with a clearing break, when saving to DOCX: + loadAndSave("clearing-break.docx"); + + // Then make sure that the clearing break is not lost: + xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); + // Without the accompanying fix in place, this test would have failed with: + // - XPath '/w:document/w:body/w:p/w:r/w:br' number of nodes is incorrect + // i.e. first the clearing break was turned into a plain break, then it was completely lost. + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:br", "clear", "all"); +} + DECLARE_OOXMLEXPORT_TEST(testTdf137466, "tdf137466.docx") { xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 1694b9335cb5..8461f2e1510c 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -507,6 +507,9 @@ protected: /// Sfx item RES_TXTATR_FTN virtual void TextFootnote_Impl( const SwFormatFootnote& ) = 0; + /// RES_TXTATR_LINEBREAK, i.e. clearing breaks. + virtual void TextLineBreak(const SwFormatLineBreak&) = 0; + /// Sfx item RES_PARATR_LINESPACING void ParaLineSpacing( const SvxLineSpacingItem& ); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index a08a16919e8d..6f3601ff0815 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3097,6 +3097,8 @@ void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData ) // write footnotes/endnotes if we have any FootnoteEndnoteReference(); + WriteLineBreak(); + // merge the properties _before_ the run text (strictly speaking, just // after the start of the run) m_pSerializer->mergeTopMarks(Tag_StartRunProperties, sax_fastparser::MergeMarks::PREPEND); @@ -7186,6 +7188,40 @@ void DocxAttributeOutput::SectionRtlGutter(const SfxBoolItem& rRtlGutter) m_pSerializer->singleElementNS(XML_w, XML_rtlGutter); } +void DocxAttributeOutput::TextLineBreak(const SwFormatLineBreak& rLineBreak) +{ + m_oLineBreakClear = rLineBreak.GetValue(); +} + +void DocxAttributeOutput::WriteLineBreak() +{ + if (!m_oLineBreakClear.has_value()) + { + return; + } + + rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList(); + pAttr->add(FSNS(XML_w, XML_type), "textWrapping"); + switch (*m_oLineBreakClear) + { + case SwLineBreakClear::NONE: + pAttr->add(FSNS(XML_w, XML_clear), "none"); + break; + case SwLineBreakClear::LEFT: + pAttr->add(FSNS(XML_w, XML_clear), "left"); + break; + case SwLineBreakClear::RIGHT: + pAttr->add(FSNS(XML_w, XML_clear), "right"); + break; + case SwLineBreakClear::ALL: + pAttr->add(FSNS(XML_w, XML_clear), "all"); + break; + } + m_oLineBreakClear.reset(); + + m_pSerializer->singleElementNS(XML_w, XML_br, pAttr); +} + void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo ) { rtl::Reference<FastAttributeList> pAttr = FastSerializerHelper::createAttrList(); diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index cac04054f542..934247ab533d 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -51,6 +51,7 @@ class SwGrfNode; class SdrObject; enum class SvxBoxItemLine; +enum class SwLineBreakClear; namespace docx { class FootnotesList; } namespace oox::drawingml { class DrawingML; } @@ -717,6 +718,11 @@ protected: void SectionRtlGutter( const SfxBoolItem& rRtlGutter) override; + void TextLineBreak(const SwFormatLineBreak& rLineBreak) override; + + /// Writes a clearing line break at the end of run properties, if there are any. + void WriteLineBreak(); + /// Reference to the export, where to get the data from DocxExport &m_rExport; @@ -1022,6 +1028,8 @@ private: std::vector<std::map<SvxBoxItemLine, css::table::BorderLine2>> m_aTableStyleConfs; + std::optional<SwLineBreakClear> m_oLineBreakClear; + public: DocxAttributeOutput( DocxExport &rExport, const ::sax_fastparser::FSHelperPtr& pSerializer, oox::drawingml::DrawingML* pDrawingML ); diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 153669189ed6..925b8ddbf016 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -4397,4 +4397,6 @@ void RtfAttributeOutput::SectionRtlGutter(const SfxBoolItem& rRtlGutter) m_rExport.Strm().WriteCharPtr(LO_STRING_SVTOOLS_RTF_RTLGUTTER); } +void RtfAttributeOutput::TextLineBreak(const SwFormatLineBreak& /*rLineBreak*/) {} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index c07f3e525501..aedef264b7d2 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -462,6 +462,8 @@ protected: void SectionRtlGutter(const SfxBoolItem& rRtlGutter) override; + void TextLineBreak(const SwFormatLineBreak& rLineBreak) override; + private: /// Reference to the export, where to get the data from RtfExport& m_rExport; diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index fcadda82f7c8..b9ec65d4cfc9 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -4185,6 +4185,8 @@ void WW8AttributeOutput::SectionRtlGutter(const SfxBoolItem& rRtlGutter) m_rWW8Export.pO->push_back(1); } +void WW8AttributeOutput::TextLineBreak(const SwFormatLineBreak& /*rLineBreak*/) {} + void WW8AttributeOutput::FormatULSpace( const SvxULSpaceItem& rUL ) { // Flys are still missing ( see RTF ) @@ -5590,6 +5592,9 @@ void AttributeOutputBase::OutputItem( const SfxPoolItem& rHt ) case RES_RTL_GUTTER: SectionRtlGutter(static_cast<const SfxBoolItem&>(rHt)); break; + case RES_TXTATR_LINEBREAK: + TextLineBreak(static_cast<const SwFormatLineBreak&>(rHt)); + break; default: SAL_INFO("sw.ww8", "Unhandled SfxPoolItem with id " << rHt.Which() ); diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx index 9bd1b425d39e..f459a7bf8a9c 100644 --- a/sw/source/filter/ww8/ww8attributeoutput.hxx +++ b/sw/source/filter/ww8/ww8attributeoutput.hxx @@ -436,6 +436,8 @@ protected: void SectionRtlGutter( const SfxBoolItem& rRtlGutter) override; + void TextLineBreak(const SwFormatLineBreak& rLineBreak) override; + /// Reference to the export, where to get the data from WW8Export &m_rWW8Export;