sw/inc/dcontact.hxx                  |    4 ++--
 sw/qa/extras/mailmerge/mailmerge.cxx |    2 +-
 sw/source/core/draw/dcontact.cxx     |   27 ++++++++++++++++++++++++---
 sw/source/core/inc/flyfrm.hxx        |    2 +-
 sw/source/core/layout/fly.cxx        |    6 +++---
 5 files changed, 31 insertions(+), 10 deletions(-)

New commits:
commit 9471458c66ad5eb52552bd65b4ac8c405682d051
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Mar 5 21:06:28 2021 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu Jun 23 18:34:42 2022 +0200

    tdf#140292: (related: tdf#133487) sw: fix ordering of virtual SdrObjects 
for textboxes
    
    Calling XShapes3::sort() on export of the testTdf130314 fails because of
    2 consecutive textboxes; the function requires a textbox to immediately
    follow its shape in the list (i.e. textbox has OrdNum of shape + 1).
    
    This is because for shapes in header/footer, one virtual SdrVirtObj is
    created per page where the header/footer is shown, and the
    SwFlyDrawContact::GetOrdNumForNewRef() does not take textbox ordering
    into account.
    
    It's not clear if the assumption that the shape's SdrVirtObj is created
    before the textbox's always holds, but let's try this for now.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112029
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112272
    (cherry picked from commit 18397b2ede1e6c3feb54bd2bf59da57fd8c4d13a)
    
    Change-Id: I860896471211bf6c142ab825f298f4d4c0eec148
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136309
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/inc/dcontact.hxx b/sw/inc/dcontact.hxx
index daec75ea300f..8d0e03d66e50 100644
--- a/sw/inc/dcontact.hxx
+++ b/sw/inc/dcontact.hxx
@@ -179,13 +179,13 @@ private:
 
     SwFlyDrawObjPtr mpMasterObj;
     void SwClientNotify(const SwModify&, const SfxHint& rHint) override;
-    sal_uInt32 GetOrdNumForNewRef(const SwFlyFrame* pFly);
+    sal_uInt32 GetOrdNumForNewRef(const SwFlyFrame* pFly, SwFrame const& 
rAnchorFrame);
 
 public:
 
     /// Creates DrawObject and registers it with the Model.
     SwFlyDrawContact(SwFlyFrameFormat* pToRegisterIn, SdrModel& rTargetModel);
-    static SwVirtFlyDrawObj* CreateNewRef(SwFlyFrame* pFly, SwFlyFrameFormat* 
pFormat);
+    static SwVirtFlyDrawObj* CreateNewRef(SwFlyFrame* pFly, SwFlyFrameFormat* 
pFormat, SwFrame const& rAnchorFrame);
     virtual ~SwFlyDrawContact() override;
 
     virtual const SwAnchoredObject* GetAnchoredObj( const SdrObject* _pSdrObj 
) const override;
diff --git a/sw/qa/extras/mailmerge/mailmerge.cxx 
b/sw/qa/extras/mailmerge/mailmerge.cxx
index c1743bf5d911..340c69dc2ce4 100644
--- a/sw/qa/extras/mailmerge/mailmerge.cxx
+++ b/sw/qa/extras/mailmerge/mailmerge.cxx
@@ -394,7 +394,7 @@ DECLARE_FILE_MAILMERGE_TEST(testMissingDefaultLineColor, 
"missing-default-line-c
     // (see XMLGraphicsDefaultStyle::SetDefaults()).
     uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<container::XIndexAccess> xDraws = 
xDrawPageSupplier->getDrawPage();
-    uno::Reference<beans::XPropertySet> xPropertySet(xDraws->getByIndex(0), 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xPropertySet(xDraws->getByIndex(4), 
uno::UNO_QUERY);
     // Lines do not have a line color.
     CPPUNIT_ASSERT( !xPropertySet->getPropertySetInfo()->hasPropertyByName( 
"LineColor" ));
     SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument 
*>(mxComponent.get());
diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx
index 9d057bcabc7d..d9e7ce725ed1 100644
--- a/sw/source/core/draw/dcontact.cxx
+++ b/sw/source/core/draw/dcontact.cxx
@@ -476,8 +476,28 @@ SwFlyDrawContact::~SwFlyDrawContact()
     }
 }
 
-sal_uInt32 SwFlyDrawContact::GetOrdNumForNewRef(const SwFlyFrame* pFly)
+sal_uInt32 SwFlyDrawContact::GetOrdNumForNewRef(const SwFlyFrame* pFly,
+        SwFrame const& rAnchorFrame)
 {
+    // maintain invariant that a shape's textbox immediately follows the shape
+    // also for the multiple SdrVirtObj created for shapes in header/footer
+    if (SwFrameFormat const*const pDrawFormat =
+            SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT))
+    {
+        // assume that the draw SdrVirtObj is always created before the 
flyframe one
+        if (SwSortedObjs const*const pObjs = rAnchorFrame.GetDrawObjs())
+        {
+            for (SwAnchoredObject const*const pAnchoredObj : *pObjs)
+            {
+                if (&pAnchoredObj->GetFrameFormat() == pDrawFormat)
+                {
+                    return pAnchoredObj->GetDrawObj()->GetOrdNum() + 1;
+                }
+            }
+        }
+        // if called from AppendObjs(), this is a problem; if called from 
lcl_SetFlyFrameAttr() it's not
+        SAL_INFO("sw", "GetOrdNumForNewRef: cannot find SdrObject for text 
box's shape");
+    }
     // search for another Writer fly frame registered at same frame format
     SwIterator<SwFlyFrame,SwFormat> aIter(*GetFormat());
     const SwFlyFrame* pFlyFrame(nullptr);
@@ -499,7 +519,8 @@ sal_uInt32 SwFlyDrawContact::GetOrdNumForNewRef(const 
SwFlyFrame* pFly)
     return GetMaster()->GetOrdNumDirect();
 }
 
-SwVirtFlyDrawObj* SwFlyDrawContact::CreateNewRef(SwFlyFrame* pFly, 
SwFlyFrameFormat* pFormat)
+SwVirtFlyDrawObj* SwFlyDrawContact::CreateNewRef(SwFlyFrame* pFly,
+        SwFlyFrameFormat* pFormat, SwFrame const& rAnchorFrame)
 {
     // Find ContactObject from the Format. If there's already one, we just
     // need to create a new Ref, else we create the Contact now.
@@ -526,7 +547,7 @@ SwVirtFlyDrawObj* 
SwFlyDrawContact::CreateNewRef(SwFlyFrame* pFly, SwFlyFrameFor
     // #i27030# - insert new <SwVirtFlyDrawObj> instance
     // into drawing page with correct order number
     else
-        rIDDMA.GetDrawModel()->GetPage(0)->InsertObject(pDrawObj, 
pContact->GetOrdNumForNewRef(pFly));
+        rIDDMA.GetDrawModel()->GetPage(0)->InsertObject(pDrawObj, 
pContact->GetOrdNumForNewRef(pFly, rAnchorFrame));
     // #i38889# - assure, that new <SwVirtFlyDrawObj> instance
     // is in a visible layer.
     pContact->MoveObjToVisibleLayer(pDrawObj);
diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx
index b53f637461fb..29a196944fcb 100644
--- a/sw/source/core/inc/flyfrm.hxx
+++ b/sw/source/core/inc/flyfrm.hxx
@@ -64,7 +64,7 @@ class SW_DLLPUBLIC SwFlyFrame : public SwLayoutFrame, public 
SwAnchoredObject
     friend void Notify( SwFlyFrame *, SwPageFrame *pOld, const SwRect &rOld,
                         const SwRect* pOldPrt );
 
-    void InitDrawObj();     // these to methods are called in the
+    void InitDrawObj(SwFrame const&); // these to methods are called in the
     void FinitDrawObj();    // constructors
 
     void UpdateAttr_( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 &,
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index 89f47ccf7632..23c815c3c994 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -165,7 +165,7 @@ SwFlyFrame::SwFlyFrame( SwFlyFrameFormat *pFormat, SwFrame* 
pSib, SwFrame *pAnch
     // First the Init, then the Content:
     // This is due to the fact that the Content may have Objects/Frames,
     // which are then registered
-    InitDrawObj();
+    InitDrawObj(*pAnch);
 
     Chain( pAnch );
 
@@ -361,10 +361,10 @@ void SwFlyFrame::DeleteCnt()
     InvalidatePage();
 }
 
-void SwFlyFrame::InitDrawObj()
+void SwFlyFrame::InitDrawObj(SwFrame const& rAnchorFrame)
 {
     // OD 2004-03-22 #i26791#
-    SetDrawObj(*SwFlyDrawContact::CreateNewRef(this, GetFormat()));
+    SetDrawObj(*SwFlyDrawContact::CreateNewRef(this, GetFormat(), 
rAnchorFrame));
 
     // Set the right Layer
     // OD 2004-01-19 #110582#

Reply via email to