sw/qa/core/text/text.cxx | 42 +++++++++++++++++++++++++++++++++++++++++ sw/source/core/text/porrst.cxx | 8 ++++++- 2 files changed, 49 insertions(+), 1 deletion(-)
New commits: commit 4e329f50e42c91704b84b1fc583d6815ab22adab Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Jul 27 16:35:13 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 27 20:25:20 2022 +0200 tdf#148291 sw clearing breaks: fix RTL layout The bugreport has two documents that show clear=left and clear=right is basically ignored in Word in the RTL paragraph case, while clear=none and clear=all work as expected. There was no special-casing for RTL in SwBreakPortion::Format() previously, as the OOXML spec does talk about left/right even in case of RTL, i.e. no expected mirroring is documented as the behavior. Looking at [MS-OI29500], "2.1.528 Part 1 Section 17.18.3, ST_BrClear" does say that the Word "behaves unpredictably" in the normal (non-web) layout. Fix the problem by handling clear=left and clear=right as clear=none in the RTL case, this fixes the rendering differences for both bugdocuments. If later we do want the mirrored layout, then such mirroring could be done in SwTextFly::GetMaxBottom(). Change-Id: I6265e64540fa9e5b893cfbea146152854416dce2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137507 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx index f11c6da8ff5d..ddd39bff7b9f 100644 --- a/sw/qa/core/text/text.cxx +++ b/sw/qa/core/text/text.cxx @@ -12,6 +12,7 @@ #include <memory> #include <com/sun/star/text/BibliographyDataType.hpp> +#include <com/sun/star/text/WritingMode2.hpp> #include <vcl/gdimtf.hxx> #include <vcl/filter/PDFiumLibrary.hxx> @@ -370,6 +371,47 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testClearingLineBreakLeft) assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "height", "2837"); } +CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testClearingLineBreakLeftRTL) +{ + // Given a document with an anchored object in an RTL para and a clearing break (type=left): + loadURL("private:factory/swriter", nullptr); + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + uno::Reference<beans::XPropertySet> xCursorProps(xCursor, uno::UNO_QUERY); + xCursorProps->setPropertyValue("WritingMode", uno::Any(text::WritingMode2::RL_TB)); + { + uno::Reference<drawing::XShape> xShape( + xFactory->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY); + xShape->setSize(awt::Size(5000, 5000)); + uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY); + xShapeProps->setPropertyValue("AnchorType", + uno::Any(text::TextContentAnchorType_AT_CHARACTER)); + uno::Reference<text::XTextContent> xShapeContent(xShape, uno::UNO_QUERY); + xText->insertTextContent(xCursor, xShapeContent, /*bAbsorb=*/false); + } + uno::Reference<text::XTextContent> xLineBreak( + xFactory->createInstance("com.sun.star.text.LineBreak"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY); + auto eClear = static_cast<sal_Int16>(SwLineBreakClear::RIGHT); + xLineBreakProps->setPropertyValue("Clear", uno::Any(eClear)); + xText->insertString(xCursor, "foo", /*bAbsorb=*/false); + xText->insertTextContent(xCursor, xLineBreak, /*bAbsorb=*/false); + xText->insertString(xCursor, "bar", /*bAbsorb=*/false); + + // When laying out that document: + calcLayout(); + + // Then make sure the "bar" does not jump down (due to type=left && RTL): + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 276 + // - Actual : 2837 + // i.e. left/right was not ignored in the RTL case. + assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "height", "276"); +} + CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testClearingLineBreakHeader) { // Given a document with a shape in the header and a clearing break in the body text: diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx index 256a43367070..0afa5ef37fcd 100644 --- a/sw/source/core/text/porrst.cxx +++ b/sw/source/core/text/porrst.cxx @@ -178,7 +178,13 @@ bool SwBreakPortion::Format( SwTextFormatInfo &rInf ) // See if this is a clearing break. If so, calculate how much we need to "jump down" so the next // line can again use the full text width. - if (m_eClear != SwLineBreakClear::NONE) + SwLineBreakClear eClear = m_eClear; + if (rInf.GetTextFrame()->IsRightToLeft() && eClear != SwLineBreakClear::ALL) + { + // RTL ignores left/right breaks. + eClear = SwLineBreakClear::NONE; + } + if (eClear != SwLineBreakClear::NONE) { SwTextFly& rTextFly = rInf.GetTextFly(); if (rTextFly.IsOn())