sw/qa/extras/ooxmlexport/ooxmlexport9.cxx                          |    9 +++
 sw/qa/extras/ooxmlimport/ooxmlimport.cxx                           |    8 ++
 sw/source/core/inc/anchoredobjectposition.hxx                      |    4 +
 sw/source/core/objectpositioning/anchoredobjectposition.cxx        |   29 
+++++++++-
 sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx |   10 +--
 5 files changed, 54 insertions(+), 6 deletions(-)

New commits:
commit 1de6bea27ed36167ec138818607da7b49e92ec4a
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Wed Aug 28 09:30:18 2024 -0400
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Sep 9 12:48:11 2024 +0200

    tdf#143899 compat15 layout: restrict body fly to PAGE_PRINT_AREA
    
    For some inexplicable reason,
    Microsoft decided to change a non-table layout restriction
    for DOCX >= 2013.
    
    Now most floating objects are not allowed to cross
    the vertical margin (header/footer) boundaries
    (although floating tables are one exception)
    (and so are framePr textboxes)
    (and horizontal margin boundaries can still be crossed).
    
    This is similar to layoutInCell's
    whimsical vertical aversion to margins.
    
    There are already good unit tests in place
    to ensure compat14 works, and for the compat15 table exception.
    (see earlier patchsets for all affected unit tests)
    
    make CppunitTest_sw_ooxmlexport9 CPPUNIT_TEST_NAME=testTdf103544
    make CppunitTest_sw_ooxmlexport21 CPPUNIT_TEST_NAME=testTdf143899
    
    Change-Id: I5788c35e57cbc84a6b5fcd0ef97dc4394b0f6395
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172536
    Reviewed-by: Justin Luth <jl...@mail.com>
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index 02b0f9466600..99e56fed1f19 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -721,6 +721,15 @@ DECLARE_OOXMLEXPORT_TEST(testTdf103544, "tdf103544.docx")
     uno::Reference<beans::XPropertySet> xImage(getShape(1), uno::UNO_QUERY);
     auto xGraphic = getProperty<uno::Reference<graphic::XGraphic> >(xImage, 
u"Graphic"_ustr);
     CPPUNIT_ASSERT(xGraphic.is());
+
+    // tdf#143899: framePr textbox not affected by compat15's aversion to 
vertical page margin
+    // The textbox requests to be 0.72inch above its anchor paragraph (the 
first paragraph)
+    xmlDocUniquePtr pDump = parseLayoutDump();
+    CPPUNIT_ASSERT_EQUAL(OUString("Frame"), getXPathContent(pDump, 
"//fly[2]/txt"_ostr));
+    sal_Int32 nShapeBottom = getXPath(pDump, "//fly[2]/infos/bounds"_ostr, 
"bottom"_ostr).toInt32();
+    sal_Int32 nBodyTop = getXPath(pDump, "//page/body/infos/bounds"_ostr, 
"top"_ostr).toInt32();
+    // The framePr textbox is NOT vertically limited like other shapes to the 
page margins
+    CPPUNIT_ASSERT(nBodyTop > nShapeBottom); // textbox is fully above the 
text body area
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTdf103573, "tdf103573.docx")
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index 7e0a1a7676c3..6b109ec3aa62 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -1459,6 +1459,14 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf60351)
     CPPUNIT_ASSERT_EQUAL(sal_Int32(316), aPolygon[4].Y);
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0),   aPolygon[5].X);
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0),   aPolygon[5].Y);
+
+    // tdf143899: image affected by compat15's aversion to vertical page 
margin.
+    // although the image is set to -0.3cm above the first paragraph, it can't 
move up at all.
+    xmlDocUniquePtr pDump = parseLayoutDump();
+    sal_Int32 nBodyTop = getXPath(pDump, "//page/body/infos/bounds"_ostr, 
"top"_ostr).toInt32();
+    sal_Int32 nImageTop = getXPath(pDump, "//fly/infos/bounds"_ostr, 
"top"_ostr).toInt32();
+    // The image (like most floating objects) is vertically limited to the 
page margins
+    CPPUNIT_ASSERT_EQUAL(nBodyTop, nImageTop);
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testTdf95970)
diff --git a/sw/source/core/inc/anchoredobjectposition.hxx 
b/sw/source/core/inc/anchoredobjectposition.hxx
index a3668330006e..2d87b5bde9bd 100644
--- a/sw/source/core/inc/anchoredobjectposition.hxx
+++ b/sw/source/core/inc/anchoredobjectposition.hxx
@@ -20,6 +20,7 @@
 #ifndef INCLUDED_SW_SOURCE_CORE_INC_ANCHOREDOBJECTPOSITION_HXX
 #define INCLUDED_SW_SOURCE_CORE_INC_ANCHOREDOBJECTPOSITION_HXX
 
+#include <fmtornt.hxx>
 #include <swtypes.hxx>
 #include "frame.hxx"
 #include <nodeoffset.hxx>
@@ -72,6 +73,7 @@ namespace objectpositioning
                                        const bool bVert,
                                        const bool bVertL2R,
                                        const SwFrame&  rPageAlignLayFrame,
+                                       const SwFormatVertOrient& rVertOrient,
                                        const SwTwips nProposedRelPosY,
                                        const bool bFollowTextFlow,
                                        const bool bCheckBottom ) const;
@@ -184,6 +186,7 @@ namespace objectpositioning
                                           const bool bVert,
                                           const bool bVertL2R,
                                           const SwFrame& rPageAlignLayFrame,
+                                          const SwFormatVertOrient& 
rVertOrient,
                                           const SwTwips nProposedRelPosY,
                                           const bool bFollowTextFlow,
                                           const bool bCheckBottom = true ) 
const
@@ -191,6 +194,7 @@ namespace objectpositioning
             return !mbDoNotCaptureAnchoredObj
                    ? ImplAdjustVertRelPos( nTopOfAnch, bVert, bVertL2R,
                                             rPageAlignLayFrame,
+                                            rVertOrient,
                                             nProposedRelPosY,
                                             bFollowTextFlow,
                                             bCheckBottom )
diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
index 11f14c3a41a3..667a88b9a9ec 100644
--- a/sw/source/core/objectpositioning/anchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
@@ -18,9 +18,11 @@
  */
 
 #include <anchoredobjectposition.hxx>
+#include <bodyfrm.hxx>
 #include <environmentofanchoredobject.hxx>
 #include <flyfrm.hxx>
 #include <flyfrms.hxx>
+#include <formatflysplit.hxx>
 #include <txtfrm.hxx>
 #include <pagefrm.hxx>
 #include <frmatr.hxx>
@@ -433,6 +435,7 @@ SwTwips SwAnchoredObjectPosition::ImplAdjustVertRelPos( 
const SwTwips nTopOfAnch
                                                          const bool bVert,
                                                          const bool bVertL2R,
                                                          const SwFrame& 
rPageAlignLayFrame,
+                                                         const 
SwFormatVertOrient& rVertOrient,
                                                          const SwTwips 
nProposedRelPosY,
                                                          const bool 
bFollowTextFlow,
                                                          const bool 
bCheckBottom ) const
@@ -471,7 +474,31 @@ SwTwips SwAnchoredObjectPosition::ImplAdjustVertRelPos( 
const SwTwips nTopOfAnch
              ( !bFollowTextFlow ||
                !GetAnchoredObj().GetAnchorFrame()->IsInTab() ) )
         {
-            aPgAlignArea = rPageAlignLayFrame.FindPageFrame()->getFrameArea();
+            const SwPageFrame& rPageFrame = 
*rPageAlignLayFrame.FindPageFrame();
+            aPgAlignArea = rPageFrame.getFrameArea();
+
+            // re-using existing compat option to determine old (<=compat14) 
behaviour
+            const bool bCompat15 = 
!rIDSA.get(DocumentSettingId::ADD_FLY_OFFSETS);
+
+            // Instead of using the top of the page as the vertical limit,
+            // DOCX compatibilityMode 15 started to use the text body as the 
vertical limit
+            // for most paragraph or line-oriented anchored non-wrapthrough 
objects.
+            // Floating tables are an exception.
+            const bool bIsFloatingTable = 
mpFrameFormat->GetFlySplit().GetValue();
+            // FramePr paragraph-defined textboxes are another exception.
+            // bVert is also untouched to avoid issues: who knows what should 
happen in that case.
+            if (!bVert && bCompat15 && !bWrapThrough && !bIsFloatingTable
+                && rPageAlignLayFrame.IsPageFrame()
+                && rVertOrient.GetRelationOrient() != 
text::RelOrientation::PAGE_FRAME
+                && rVertOrient.GetRelationOrient() != 
text::RelOrientation::PAGE_PRINT_AREA
+                && !SwTextBoxHelper::TextBoxIsFramePr(*mpFrameFormat))
+            {
+                const SwBodyFrame* pBodyFrame = mpAnchorFrame->FindBodyFrame();
+                while (pBodyFrame && !pBodyFrame->IsPageBodyFrame())
+                    pBodyFrame = pBodyFrame->GetUpper()->FindBodyFrame();
+                if (pBodyFrame)
+                    aPgAlignArea = pBodyFrame->getFrameArea();
+            }
         }
         else
         {
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx 
b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 71b062232907..f5d7a79f9de8 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -457,7 +457,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                                             *(pOrientFrame->GetUpper()) );
                 const bool bCheckBottom = !DoesObjFollowsTextFlow();
                 nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), 
aRectFnSet.IsVertL2R(),
-                                              rVertEnvironLayFrame, nRelPosY,
+                                              rVertEnvironLayFrame, aVert, 
nRelPosY,
                                               DoesObjFollowsTextFlow(),
                                               bCheckBottom );
             }
@@ -680,7 +680,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                 // anchored object has to follow the text flow.
                 const bool bCheckBottom = !DoesObjFollowsTextFlow();
                 nRelPosY = AdjustVertRelPos( nTopOfAnch, aRectFnSet.IsVert(), 
aRectFnSet.IsVertL2R(),
-                                              rVertEnvironLayFrame, nRelPosY,
+                                              rVertEnvironLayFrame, aVert, 
nRelPosY,
                                               !bIgnoreVertLayoutInCell && 
DoesObjFollowsTextFlow(),
                                               bCheckBottom );
                 if ( aRectFnSet.IsVert() )
@@ -720,7 +720,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                         // frame, if anchored object has to follow the text 
flow.
                         const bool bCheckBottom = !DoesObjFollowsTextFlow();
                         nTmpRelPosY = AdjustVertRelPos( nTopOfAnch, 
aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
-                                                         rVertEnvironLayFrame,
+                                                         rVertEnvironLayFrame, 
aVert,
                                                          nTmpRelPosY,
                                                          
DoesObjFollowsTextFlow(),
                                                          bCheckBottom );
@@ -811,7 +811,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                             const SwFrame& rVertEnvironLayFrame =
                                 aEnvOfObj.GetVertEnvironmentLayoutFrame( 
*pUpperOfOrientFrame );
                             nRelPosY = AdjustVertRelPos( nTopOfAnch, 
aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
-                                                          rVertEnvironLayFrame,
+                                                          
rVertEnvironLayFrame, aVert,
                                                           nRelPosY,
                                                           
DoesObjFollowsTextFlow() );
                             if( aRectFnSet.IsVert() )
@@ -938,7 +938,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
                     const SwLayoutFrame& rVertEnvironLayFrame =
                         aEnvOfObj.GetVertEnvironmentLayoutFrame( 
*pUpperOfOrientFrame );
                     nTmpRelPosY = AdjustVertRelPos( nTopOfAnch, 
aRectFnSet.IsVert(), aRectFnSet.IsVertL2R(),
-                                                     rVertEnvironLayFrame,
+                                                     rVertEnvironLayFrame, 
aVert,
                                                      nTmpRelPosY,
                                                      DoesObjFollowsTextFlow(),
                                                      false );

Reply via email to