tdf#136516 add positioning to SwTextBoxHelper::syncProperty()

Before when the shape of the textbox moved, the anchor
and the position synched. However if the new position
of the shape required new anchor position, that was not
handled. In addition after positioning and new anchor
position the sync is necessary again, because anchor
moving can change the calculated position values and
that can change the anchor etc...

The OOXMLImport test modification was necessary because
a test failed during Jenkins tests however there was
no difference between the test document before and after the
fix. In addition I can not reproduce the fail of the test
in my local repository, and only the Linux- and Windows
builds showed the problem.

Solved also tdf#138951, tdf#139686 and tdf#139092.

Change-Id: Ibdfff89db01d75aeae74948e2ea41ce5a613b6fa
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109365
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/layout/data/tdf138951.odt b/sw/qa/extras/layout/data/tdf138951.odt
new file mode 100755
index 0000000..5cb4940
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf138951.odt
Binary files differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 253783a..b84a2c5 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -26,6 +26,7 @@
#include <comphelper/sequence.hxx>

#include <fmtfsize.hxx>
#include <fmtornt.hxx>
#include <wrtsh.hxx>
#include <edtwin.hxx>
#include <view.hxx>
@@ -283,6 +284,37 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineShowHideFootnotePagination)
                "zzz. zzz zzzz zzzz7 zzz zzz zzzzzzz zzz zzzz zzzzzzzzzzzzzz zzzzzzzzzzzz ");
}

CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testtdf138951)
{
    // Open the bugdoc
    auto pDoc = createDoc("tdf138951.odt");

    // Get the only shape
    uno::Reference<drawing::XShape> xShape(getShape(1), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xShape);

    // Gather its formats: the shape and textbox
    const SwFrameFormat* pTxFrm = SwTextBoxHelper::getOtherTextBoxFormat(xShape);
    CPPUNIT_ASSERT(pTxFrm);
    const SwFrameFormat* pShFrm = SwTextBoxHelper::getOtherTextBoxFormat(pTxFrm, RES_FLYFRMFMT);
    CPPUNIT_ASSERT(pShFrm);

    pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();

    // Get the bound rectangle of the textframe
    tools::Rectangle aTxtFrmRect(pTxFrm->FindRealSdrObject()->GetLogicRect());

    // Get the bound rectangle of the shape
    tools::Rectangle aShpRect(pShFrm->FindRealSdrObject()->GetLogicRect());

    // Check the anchor the same and the textbox is inside the shape
    const bool bIsAnchTheSame
        = *pShFrm->GetAnchor().GetContentAnchor() == *pShFrm->GetAnchor().GetContentAnchor();
    CPPUNIT_ASSERT_MESSAGE("The anchor is different for the textbox and shape!", bIsAnchTheSame);
    CPPUNIT_ASSERT_MESSAGE("The textbox has fallen apart!", aShpRect.IsInside(aTxtFrmRect));
    // Without the fix the anchor differs, and the frame ouside of the shape
}

CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumberInNumbering)
{
    SwDoc* pDoc = createDoc("tdf42748.fodt");
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index f711423..474cfbe 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -28,6 +28,7 @@

#include <wrtsh.hxx>
#include <IDocumentMarkAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IMark.hxx>
#include <sortedobjs.hxx>
#include <anchoredobject.hxx>
@@ -36,6 +37,7 @@
#include <unotxdoc.hxx>
#include <docsh.hxx>
#include <rootfrm.hxx>
#include <frame.hxx>

class Test : public SwModelTestBase
{
@@ -398,8 +400,17 @@ DECLARE_OOXMLIMPORT_TEST(testTdf112443, "tdf112443.docx")
{
    // the position of the flying text frame should be off page
    // 30624 below its anchor
    OUString aTop = parseDump("//fly[1]/infos/bounds", "top");
    CPPUNIT_ASSERT_EQUAL(OUString("30624"), aTop);
    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pTextDoc);
    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
    SwRootFrame* pRootFrame = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
    const SwRect aPageRect = pRootFrame->getFrameArea();
    const SwRect aShapeRect(getShape(1)->getPosition().X, getShape(1)->getPosition().Y,
                            getShape(1)->getSize().Width, getShape(1)->getSize().Height);
    CPPUNIT_ASSERT_MESSAGE("The textframe must be off-page!", !aPageRect.IsInside(aShapeRect));

    //OUString aTop = parseDump("//fly[1]/infos/bounds", "top");
    //CPPUNIT_ASSERT_EQUAL(sal_Int32(30624), aTop.toInt32() );
}

// DOCX: Textbox wrap differs in MSO and LO
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 634685b..46811d5 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -721,6 +721,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
                        xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue);
                    }
                    // After anchoring the position must be set as well:
                    // At-Page anchor this will be the following:
                    if (aValue.get<text::TextContentAnchorType>()
                        == text::TextContentAnchorType::TextContentAnchorType_AT_PAGE)
                    {
@@ -728,7 +729,34 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
                            UNO_NAME_ANCHOR_PAGE_NO,
                            uno::makeAny(pShape->GetAnchor().GetPageNum()));
                    }
                    // At-Content Anchors have to be synced:
                    if (aValue.get<text::TextContentAnchorType>()
                            == text::TextContentAnchorType::TextContentAnchorType_AT_PARAGRAPH
                        || aValue.get<text::TextContentAnchorType>()
                               == text::TextContentAnchorType::TextContentAnchorType_AT_CHARACTER)
                    {
                        // If the shape has content...
                        if (auto aPos = pShape->GetAnchor().GetContentAnchor())
                        {
                            SwFormatAnchor aAnch(pFormat->GetAnchor());
                            // ...set it for the textframe too.
                            aAnch.SetAnchor(aPos);
                            pFormat->SetFormatAttr(aAnch);
                        }
                        else
                            SAL_WARN("sw.core",
                                     "SwTextBoxHelper::syncProperty: Anchor without content!");
                    }
                    // And the repositioning:
                    tools::Rectangle aRect(getTextRectangle(pShape, false));

                    SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient());
                    aNewHOri.SetPos(aNewHOri.GetPos() + aRect.getX());
                    SwFormatVertOrient aNewVOri(pShape->GetVertOrient());
                    aNewVOri.SetPos(aNewVOri.GetPos() + aRect.getY());

                    pFormat->SetFormatAttr(aNewHOri);
                    pFormat->SetFormatAttr(aNewVOri);
                    return;
                }
                break;