sw/qa/core/text/data/clearing-break-start.fodt |   28 +++++++++++++++++++++++
 sw/qa/core/text/text.cxx                       |   30 +++++++++++++++++++++++++
 sw/source/core/text/porlay.cxx                 |   19 +++++++++++++++
 3 files changed, 76 insertions(+), 1 deletion(-)

New commits:
commit cee9b476d51f770fba03cb20b58370762d387e63
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Mar 10 08:18:55 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Mar 10 09:20:28 2022 +0100

    sw clearing breaks: fix layout when the line is empty
    
    The break portion's height was not taken into account when the line had
    no text portion ("had no content"). Fix that codepath to also take the
    break portion's height into account, in case that's a clearing break.
    
    Change-Id: Ib7b338911aa23fee766423897ed131ce4029223c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131297
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/text/data/clearing-break-start.fodt 
b/sw/qa/core/text/data/clearing-break-start.fodt
new file mode 100644
index 000000000000..f2df00fadd4f
--- /dev/null
+++ b/sw/qa/core/text/data/clearing-break-start.fodt
@@ -0,0 +1,28 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+  <office:automatic-styles>
+    <style:style style:name="fr1" style:family="graphic">
+      <style:graphic-properties fo:margin-left="0.318cm" 
fo:margin-right="0.318cm" fo:margin-top="0cm" fo:margin-bottom="0cm" 
style:wrap="parallel" style:vertical-pos="from-top" 
style:vertical-rel="paragraph" style:horizontal-pos="from-left" 
style:horizontal-rel="paragraph"/>
+    </style:style>
+  </office:automatic-styles>
+  <office:body>
+    <office:text>
+      <text:p><draw:frame draw:style-name="fr1" draw:name="Picture 1" 
text:anchor-type="char" svg:x="0cm" svg:y="0cm" svg:width="1.806cm" 
svg:height="1.806cm" draw:z-index="0"><draw:image 
draw:mime-type="image/png"><office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAABGdBTUEAALGPC/xhBQAAAAFz
+       UkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA
+       AAJiS0dEAACqjSMyAAAACW9GRnMAAAAGAAAAAAAMc1XTAAAACXBIWXMAAA3XAAAN1wFCKJt4
+       AAAACXZwQWcAAABMAAAAQACdMTgbAAABzUlEQVRo3u3ZPU/CQBjA8X+Jxs3ESUDj4iK+LA5+
+       BBfjqBE1cXB2MlFAEqMgxvhNNL4sLsK3UPQL6ObkoAETz+FKW2mxCPRYnucWUu76/OC59C49
+       cGOCKqrD9kHRc6ddPv7oW2WCwMh0nF63Myz7Tm8hPTNu0pgHMER3scepTbgK6enJNND83RLn
+       /878yRaPmgBZFDuMsNLeWB9gmFQHP77MIg9gsYciR50NFKvtjIy10yk84pSZA7DYpwR8scmF
+       QQCMuoQMpzbh0iAARrlnVn90CWHTsZcAiHPPdINQAuqsc2MQAAnKDUKWEhZ10twaBEDSJWQo
+       YlFj7S9CzwEegkXWIbQsRAQASFJhpplwbRAACS+hANRJBxMiAkDcJeQ4sQkBhYgMoJ+Ozlwo
+       2YQ7AJ6CRxyiUGnVy3hVKb0Af9v7hUG2Wy9TEQCUelFTDULB2S+YKYGOMcpM6UIccOQnRA6A
+       cSp6ibfI+wkGADBGpTEd8xz1AaAfTQ7huA8AvUw5hVjuA0D/C5OaMN8XACRZ8F0zCggKAQhA
+       AAIQgAAEIAABCEAAAhCAAAQgAAH4zg3feY4w3Xs44M5+oW0qvCWoGcvaIlM3x/f/ab+O738A
+       hOCNQr34oD4AAAAldEVYdGNyZWF0ZS1kYXRlADIwMTAtMTItMjBUMTc6MDg6MzYrMDE6MDB6
+       5RscAAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEwLTEyLTIwVDE3OjA4OjM3KzAxOjAwgyNmnAAA
+       AABJRU5ErkJggg==
+      </office:binary-data></draw:image></draw:frame>X</text:p>
+    </office:text>
+  </office:body>
+</office:document>
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 39e33e01a580..317139c5ec37 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -290,6 +290,36 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testClearingLineBreak)
     assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "height", "1024");
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testClearingLineBreakAtStart)
+{
+    // Given a document with a fly frame and a character wrapped around it:
+    createSwDoc(DATA_DIRECTORY, "clearing-break-start.fodt");
+    // Insert a clearing break before "X":
+    uno::Reference<text::XTextDocument> xDocument(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+    xCursor->gotoEnd(/*bSelect=*/false);
+    xCursor->goLeft(/*nCount=*/1, /*bSelect=*/false);
+    uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
+    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::ALL);
+    xLineBreakProps->setPropertyValue("Clear", uno::makeAny(eClear));
+    xText->insertTextContent(xCursor, xLineBreak, /*bAbsorb=*/false);
+
+    // When laying out that document:
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    // Then make sure that the second line "jumps down", below the fly frame:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1024
+    // - Actual  : 276
+    // i.e. the line height was too small, but only in case the full line was 
a fly and a break
+    // portion, without any real content.
+    assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout[1]", "height", "1024");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index dcab6f1db4e9..84c6837d56c1 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -339,6 +339,10 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf )
     sal_uInt16 nFlyAscent = 0;
     sal_uInt16 nFlyHeight = 0;
     sal_uInt16 nFlyDescent = 0;
+
+    // If this line has a clearing break, then this is the portion's height.
+    sal_uInt16 nBreakHeight = 0;
+
     bool bOnlyPostIts = true;
     SetHanging( false );
 
@@ -455,6 +459,7 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf )
                 {
                     auto pBreakPortion = static_cast<SwBreakPortion*>(pPos);
                     bClearingBreak = pBreakPortion->GetClear() != 
SwLineBreakClear::NONE;
+                    nBreakHeight = nPosHeight;
                 }
                 if (!(pPos->IsBreakPortion() && !bClearingBreak) || !Height())
                 {
@@ -569,7 +574,19 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf )
                 if( nFlyDescent > nFlyHeight - nFlyAscent )
                     Height( nFlyHeight + nFlyDescent, false );
                 else
-                    Height( nFlyHeight, false );
+                {
+                    if (nBreakHeight > nFlyHeight)
+                    {
+                        // The line has no content, but it has a clearing 
break: then the line
+                        // height is not only the intersection of the fly and 
line's rectangle, but
+                        // also includes the clearing break's height.
+                        Height(nBreakHeight, false);
+                    }
+                    else
+                    {
+                        Height(nFlyHeight, false);
+                    }
+                }
             }
             else if( nMaxDescent > Height() - mnAscent )
                 Height( nMaxDescent + mnAscent, false );

Reply via email to