tdf#137980 sw textbox: fix automatic size of shapes with rotated text

If a shape+fly pair has automatic size for the fly frame, then only the
sw layout knows the necessary size, this is then sent to the shape and
SdrObjCustomShape::AdjustTextFrameWidthAndHeight() is meant to respect
those "suggestion", instead of sizing the shape based on the contained
editeng text, which is always empty for shape+fly pairs.

Improve this mechanism so it works better when the writing direction of
the fly frame is tbrl ("rotate to the right"): make sure we always grow
to the left and to the bottom, so the shape and the fly geometry
matches.

Also improve the testTextBoxSizeAtBottomOfPage "change detector" test
which had a hardcoded height, but which did not clearly derive from any
in-bugdoc value. Rather just test that the shape wider than taller,
which was probably the intention.

Change-Id: Ic6a77a1125bbf31b198aaf9048dc4812c87b4d9b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105960
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx
index 09976fa..29461df 100644
--- a/svx/source/svdraw/svdoashp.cxx
+++ b/svx/source/svdraw/svdoashp.cxx
@@ -2325,12 +2325,16 @@ bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(tools::Rectangle& rR, bool
                bWdtGrow = false;
            if ( nHgtGrow == 0 )
                bHgtGrow=false;
            if ( bWdtGrow || bHgtGrow )
            if ( bWdtGrow || bHgtGrow || !m_aSuggestedTextFrameSize.IsEmpty())
            {
                if ( bWdtGrow )
                if ( bWdtGrow || m_aSuggestedTextFrameSize.Width() )
                {
                    SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
                    if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
                    if (m_aSuggestedTextFrameSize.Width())
                    {
                        rR.SetRight(rR.Left() + m_aSuggestedTextFrameSize.Width());
                    }
                    else if ( eHAdj == SDRTEXTHORZADJUST_LEFT )
                        rR.AdjustRight(nWdtGrow );
                    else if ( eHAdj == SDRTEXTHORZADJUST_RIGHT )
                        rR.AdjustLeft( -nWdtGrow );
@@ -2341,10 +2345,14 @@ bool SdrObjCustomShape::AdjustTextFrameWidthAndHeight(tools::Rectangle& rR, bool
                        rR.SetRight(rR.Left()+nWdt );
                    }
                }
                if ( bHgtGrow )
                if ( bHgtGrow || m_aSuggestedTextFrameSize.Height() )
                {
                    SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
                    if ( eVAdj == SDRTEXTVERTADJUST_TOP )
                    if (m_aSuggestedTextFrameSize.Height())
                    {
                        rR.SetBottom(rR.Top() + m_aSuggestedTextFrameSize.Height());
                    }
                    else if ( eVAdj == SDRTEXTVERTADJUST_TOP )
                        rR.AdjustBottom(nHgtGrow );
                    else if ( eVAdj == SDRTEXTVERTADJUST_BOTTOM )
                        rR.AdjustTop( -nHgtGrow );
diff --git a/sw/qa/core/layout/data/textbox-autogrow-vertical.docx b/sw/qa/core/layout/data/textbox-autogrow-vertical.docx
new file mode 100644
index 0000000..0cc45a7
--- /dev/null
+++ b/sw/qa/core/layout/data/textbox-autogrow-vertical.docx
Binary files differ
diff --git a/sw/qa/core/layout/layout.cxx b/sw/qa/core/layout/layout.cxx
index b66a4f5..15f2c4e 100644
--- a/sw/qa/core/layout/layout.cxx
+++ b/sw/qa/core/layout/layout.cxx
@@ -180,6 +180,28 @@ CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testTextBoxStaysInsideShape)
    assertXPath(pXmlDoc, "//fly/infos/bounds", "bottom", "7184");
}

CPPUNIT_TEST_FIXTURE(SwCoreLayoutTest, testTextBoxAutoGrowVertical)
{
    load(DATA_DIRECTORY, "textbox-autogrow-vertical.docx");
    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
    SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
    SdrObject* pShape = pPage->GetObj(0);
    tools::Rectangle aShapeRect = pShape->GetCurrentBoundRect();

    discardDumpedLayout();
    xmlDocUniquePtr pLayout = parseLayoutDump();
    CPPUNIT_ASSERT(pLayout);
    sal_Int32 nFlyLeft = getXPath(pLayout, "//fly/infos/bounds", "left").toInt32();
    sal_Int32 nFlyTop = getXPath(pLayout, "//fly/infos/bounds", "top").toInt32();
    sal_Int32 nFlyRight = getXPath(pLayout, "//fly/infos/bounds", "right").toInt32();
    sal_Int32 nFlyBottom = getXPath(pLayout, "//fly/infos/bounds", "bottom").toInt32();
    tools::Rectangle aFlyRect(nFlyLeft, nFlyTop, nFlyRight, nFlyBottom);
    // Without the accompanying fix in place, this test would have failed, as aFlyRect was too wide,
    // so it was not inside aShapeRect anymore.
    CPPUNIT_ASSERT(aShapeRect.IsInside(aFlyRect));
}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */