sw/qa/extras/layout/layout2.cxx      |   22 ++++++++++------------
 sw/source/core/doc/textboxhelper.cxx |   31 +++++++++++++++++++++++++------
 2 files changed, 35 insertions(+), 18 deletions(-)

New commits:
commit 0c2d2ca64f796b3f3f0bc8a8d123aa1be99414f1
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Tue Aug 6 21:57:01 2024 -0400
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Sat Aug 17 22:27:59 2024 +0200

    tdf#162211 tdf#158384 layoutInCell: doTextBoxPositioning better
    
    by simply honouring FollowTextFlow as the comment states.
    
    I needed to look into this because of a failing unit test.
    
    I can't say I understand why sync needs to lay out two things
    instead of just laying out one and copying the screen position,
    but bug 158384 indicated that the wrong value was added,
    so I looked for alternatives to use instead of nLeftSpace.
    
    A better sounding alternative was textbox spacing to border,
    but that is already taken into account.
    
    Then I realized a negative offset was being applied
    against the cell edge - which is only allowed for bWrapThrough.
    
    Unfortunately, that once again breaks the unit test
    I have been trying to accommodate.
    I can only assume that the unit test's pressuppositions are false.
    So I'm changing the unit test to test things that are certain!
    make CppunitTest_sw_layoutwriter2 CPPUNIT_TEST_NAME=testTdf116256
    
    Given how wonky textbox sync is,
    I'm not confident that ANYTHING here is actually correct.
    
    Change-Id: I2e73b7345b4d4c3da78d62644032cb573dc6821e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171577
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>

diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 8226c5100c78..50f2cba4d986 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -1756,16 +1756,14 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116256)
     // Parse the layout
     auto pLayout = parseLayoutDump();
     // Get the position of the shape
-    const auto nTextBoxShapeLeft = getXPath(pLayout,
-                                            
"/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/"
-                                            
"anchored/SwAnchoredDrawObject/bounds"_ostr,
-                                            "left"_ostr)
-                                       .toInt64();
-    const auto nTextBoxShapeTop = getXPath(pLayout,
-                                           
"/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/"
-                                           
"anchored/SwAnchoredDrawObject/bounds"_ostr,
-                                           "top"_ostr)
-                                      .toInt64();
+    const auto nCellLeft
+        = getXPath(pLayout, 
"//page/body/txt/anchored/fly/tab/row[1]/cell/infos/bounds"_ostr,
+                   "left"_ostr)
+              .toInt64();
+    const auto nCellTop
+        = getXPath(pLayout, 
"//page/body/txt/anchored/fly/tab/row[1]/cell/infos/bounds"_ostr,
+                   "top"_ostr)
+              .toInt64();
     // Get the position of the textframe too.
     const auto nTextBoxFrameLeft
         = getXPath(
@@ -1781,8 +1779,8 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116256)
               .toInt64();
 
     // Without the fix in place these were less than they supposed to.
-    CPPUNIT_ASSERT_GREATEREQUAL(nTextBoxShapeLeft, nTextBoxFrameLeft);
-    CPPUNIT_ASSERT_GREATEREQUAL(nTextBoxShapeTop, nTextBoxFrameTop);
+    CPPUNIT_ASSERT_GREATEREQUAL(nCellLeft, nTextBoxFrameLeft);
+    CPPUNIT_ASSERT_GREATEREQUAL(nCellTop, nTextBoxFrameTop);
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138194)
diff --git a/sw/source/core/doc/textboxhelper.cxx 
b/sw/source/core/doc/textboxhelper.cxx
index b51a5f3c8b5c..fabc18a7e4e9 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -16,6 +16,7 @@
 #include <fmtfsize.hxx>
 #include <doc.hxx>
 #include <IDocumentLayoutAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
 #include <IDocumentState.hxx>
 #include <docsh.hxx>
 #include <unocoll.hxx>
@@ -1440,9 +1441,6 @@ bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* 
pShape, SdrObject* pOb
             tools::Rectangle aRect
                 = getRelativeTextRectangle(pObj ? pObj : 
pShape->FindRealSdrObject());
 
-            // X Offset of the shape spacing
-            auto nLeftSpace = pShape->GetLRSpace().GetLeft();
-
             // Set the same position as the (child) shape has
             SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient());
             if (bIsGroupObj && aNewHOri.GetHoriOrient() != 
text::HoriOrientation::NONE)
@@ -1482,6 +1480,14 @@ bool 
SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb
             if (pShape->GetFollowTextFlow().GetValue() && 
pShape->GetAnchor().GetAnchorNode()
                 && pShape->GetAnchor().GetAnchorNode()->FindTableNode())
             {
+                // WARNING: It is highly likely that everything here is 
simplistic and incomplete.
+
+                // Microsoft allows WrapThrough shapes to be placed outside of 
the cell
+                // despite having specified layoutInCell.
+                // (Re-using existing, appropriately-named, compat flag to 
identify MSO formats.)
+                const bool bMSOLayout = 
pFormat->getIDocumentSettingAccess().get(
+                    DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION);
+
                 // Table position
                 Point nTableOffset;
                 // Floating table
@@ -1505,12 +1511,25 @@ bool 
SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pOb
                     }
                 }
 
-                // Add the table positions to the textbox.
-                aNewHOri.SetPos(aNewHOri.GetPos() + nTableOffset.getX() + 
nLeftSpace);
+                // stay within the cell limits (since following text flow)
+                // unless this is based on a Microsoft layout which has a 
through-wrap exception.
+                bool bWrapThrough = false;
+                getShapeWrapThrough(pShape, bWrapThrough);
+                sal_Int32 nPos = aNewHOri.GetPos();
+                if (nPos < 0 && (!bMSOLayout || !bWrapThrough))
+                    nPos = 0;
+                // Add the table positions to the textbox
+                aNewHOri.SetPos(nPos + nTableOffset.getX());
+
                 if (pShape->GetVertOrient().GetRelationOrient() == 
text::RelOrientation::PAGE_FRAME
                     || pShape->GetVertOrient().GetRelationOrient()
                            == text::RelOrientation::PAGE_PRINT_AREA)
-                    aNewVOri.SetPos(aNewVOri.GetPos() + nTableOffset.getY());
+                {
+                    nPos = aNewVOri.GetPos();
+                    if (nPos < 0 && (!bMSOLayout || !bWrapThrough))
+                        nPos = 0;
+                    aNewVOri.SetPos(nPos + nTableOffset.getY());
+                }
             }
 
             pFormat->SetFormatAttr(aNewHOri);

Reply via email to