editeng/inc/editdoc.hxx                     |   14 ++
 editeng/source/editeng/impedit.hxx          |    9 +
 editeng/source/editeng/impedit2.cxx         |   22 ++++
 editeng/source/editeng/impedit3.cxx         |  139 ++++++++++++++++++++--------
 include/editeng/editdata.hxx                |    4 
 include/editeng/outliner.hxx                |    2 
 include/svx/svdotext.hxx                    |    6 -
 sd/qa/unit/TextFittingTest.cxx              |   12 +-
 sd/qa/unit/data/xml/n593612_0.xml           |    4 
 sd/qa/unit/export-tests-ooxml3.cxx          |    2 
 svx/source/svdraw/svdotext.cxx              |  133 ++++----------------------
 svx/source/svdraw/svdotextdecomposition.cxx |    4 
 svx/source/svdraw/svdotxed.cxx              |    2 
 13 files changed, 183 insertions(+), 170 deletions(-)

New commits:
commit 774c1ddfecc6389234f8d0e68d6e17c1fe218cb1
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Mar 28 12:30:34 2024 +0900
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Apr 15 14:56:31 2024 +0200

    editeng: use text scaling that better mimics MSO text scaling
    
    Implement text scaling algorithm that is similar to MSO text
    scaling for text boxes for the compatibility purpuse, so that the
    Impress slides better match how the PP slides are layed out.
    
    This also moves the implementation into EditEng, where it is
    possible to better control how searching for the best scaling
    factor is performed without doing additional irrelevant work or
    trigger invalidations that should not be triggered.
    
    An additional change is that the paragraph with no content at the
    end are ignored, and are not taken into account when determining
    the height of the content. This is done for compatibility reasons.
    
    Fix horizontal spacing of tabs - the spacing shouldn't be scaled
    and the tab shouldn't include the space at the beginning of the
    line.
    
    Change-Id: Ie37fa67f1cf300e915a4ebaef2a7f968bf6c5744
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165441
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit f61ea135430d7b4a1fac7de1e57a1314fbb1b49e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166087
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/editeng/inc/editdoc.hxx b/editeng/inc/editdoc.hxx
index 80e3cc34243c..8e17c6c38fa6 100644
--- a/editeng/inc/editdoc.hxx
+++ b/editeng/inc/editdoc.hxx
@@ -662,7 +662,9 @@ public:
 class ParaPortionList
 {
     mutable sal_Int32 nLastCache;
-    std::vector<std::unique_ptr<ParaPortion>> maPortions;
+    typedef std::vector<std::unique_ptr<ParaPortion>> ParaPortionContainerType;
+    ParaPortionContainerType maPortions;
+
 public:
                     ParaPortionList();
                     ~ParaPortionList();
@@ -684,6 +686,16 @@ public:
     void Append(std::unique_ptr<ParaPortion> p);
     sal_Int32 Count() const;
 
+    ParaPortion& getRef(sal_Int32 nPosition) { return *maPortions[nPosition]; }
+    ParaPortion const& getRef(sal_Int32 nPosition) const { return 
*maPortions[nPosition]; }
+
+    sal_Int32 lastIndex() const { return Count() - 1; }
+
+    ParaPortionContainerType::iterator begin() { return maPortions.begin(); }
+    ParaPortionContainerType::iterator end() { return maPortions.end(); }
+    ParaPortionContainerType::const_iterator cbegin() const { return 
maPortions.cbegin(); }
+    ParaPortionContainerType::const_iterator cend() const { return 
maPortions.cend(); }
+
 #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
     // temporary:
     static void DbgCheck(ParaPortionList const&, EditDoc const& rDoc);
diff --git a/editeng/source/editeng/impedit.hxx 
b/editeng/source/editeng/impedit.hxx
index 34d57e8e9747..988c446aca57 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -530,6 +530,7 @@ private:
 
     Color               maBackgroundColor;
 
+    ScalingParameters maCustomScalingParameters;
     ScalingParameters maScalingParameters;
     bool mbRoundToNearestPt;
 
@@ -617,6 +618,7 @@ private:
     void                ParaAttribsChanged( ContentNode const * pNode, bool 
bIgnoreUndoCheck = false );
     void                TextModified();
     void                CalcHeight( ParaPortion* pPortion );
+    bool isInEmptyClusterAtTheEnd(ParaPortion& rParaPortion);
 
     void                InsertUndo( std::unique_ptr<EditUndo> pUndo, bool 
bTryMerge = false );
     void                ResetUndoManager();
@@ -880,8 +882,11 @@ public:
 
     void SetMinColumnWrapHeight(tools::Long nVal) { mnMinColumnWrapHeight = 
nVal; }
 
-    void                    FormatDoc();
-    void                    FormatFullDoc();
+    tools::Long FormatParagraphs(o3tl::sorted_vector<sal_Int32>& 
rRepaintParagraphs);
+    void ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& 
rRepaintParagraphs);
+    void FormatDoc();
+    void FormatFullDoc();
+
     void                    UpdateViews( EditView* pCurView = nullptr );
     void                    Paint( ImpEditView* pView, const tools::Rectangle& 
rRect, OutputDevice* pTargetDevice );
     void                    Paint(OutputDevice& rOutDev, tools::Rectangle 
aClipRect, Point aStartPos, bool bStripOnly = false, Degree10 nOrientation = 
0_deg10);
diff --git a/editeng/source/editeng/impedit2.cxx 
b/editeng/source/editeng/impedit2.cxx
index 8c5265e1304e..048226658d4e 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -4376,12 +4376,31 @@ tools::Long ImpEditEngine::GetXPos(
     return nX;
 }
 
+/** Is true if paragraph is in the empty cluster of paragraphs at the end */
+bool ImpEditEngine::isInEmptyClusterAtTheEnd(ParaPortion& rPortion)
+{
+    sal_Int32 nPortion = GetParaPortions().GetPos(&rPortion);
+
+    auto& rParagraphs = GetParaPortions();
+    if (rParagraphs.Count() <= 0)
+        return false;
+
+    sal_Int32 nCurrent = rParagraphs.lastIndex();
+    while (nCurrent > 0 && rParagraphs.getRef(nCurrent).IsEmpty())
+    {
+        if (nCurrent == nPortion)
+            return true;
+        nCurrent--;
+    }
+    return false;
+}
+
 void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
 {
     pPortion->nHeight = 0;
     pPortion->nFirstLineOffset = 0;
 
-    if ( !pPortion->IsVisible() )
+    if (!pPortion->IsVisible() || isInEmptyClusterAtTheEnd(*pPortion))
         return;
 
     OSL_ENSURE( pPortion->GetLines().Count(), "Paragraph with no lines in 
ParaPortion::CalcHeight" );
@@ -4416,7 +4435,6 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
         pPortion->nHeight += scaleYSpacingValue(rULItem.GetLower());   // not 
in the last
     }
 
-
     if ( !nPortion || maStatus.ULSpaceSummation() )
         return;
 
diff --git a/editeng/source/editeng/impedit3.cxx 
b/editeng/source/editeng/impedit3.cxx
index 79c943516bc7..464e9ed07550 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -392,53 +392,39 @@ bool ImpEditEngine::IsPageOverflow( ) const
 
 void ImpEditEngine::FormatFullDoc()
 {
-    for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); 
nPortion++ )
-        GetParaPortions()[nPortion]->MarkSelectionInvalid( 0 );
+    for ( sal_Int32 nPortion = 0; nPortion < maParaPortionList.Count(); 
nPortion++ )
+        maParaPortionList[nPortion]->MarkSelectionInvalid( 0 );
     FormatDoc();
 }
 
-void ImpEditEngine::FormatDoc()
+tools::Long ImpEditEngine::FormatParagraphs(o3tl::sorted_vector<sal_Int32>& 
aRepaintParagraphList)
 {
-    if (!IsUpdateLayout() || IsFormatting())
-        return;
-
-    mbIsFormatting = true;
-
-    // Then I can also start the spell-timer...
-    if ( GetStatus().DoOnlineSpelling() )
-        StartOnlineSpellTimer();
-
+    sal_Int32 nParaCount = maParaPortionList.Count();
     tools::Long nY = 0;
     bool bGrow = false;
 
-    // Here already, so that not always in CreateLines...
-    bool bMapChanged = ImpCheckRefMapMode();
-    sal_Int32 nParaCount = GetParaPortions().Count();
-    o3tl::sorted_vector<sal_Int32> aRepaintParas;
-    aRepaintParas.reserve(nParaCount);
-
-    for ( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
+    for (sal_Int32 nParagraph = 0; nParagraph < nParaCount; nParagraph++)
     {
-        ParaPortion* pParaPortion = GetParaPortions()[nPara];
-        if ( pParaPortion->MustRepaint() || ( pParaPortion->IsInvalid() && 
pParaPortion->IsVisible() ) )
+        ParaPortion& rParaPortion = maParaPortionList.getRef(nParagraph);
+        if (rParaPortion.MustRepaint() || (rParaPortion.IsInvalid() && 
rParaPortion.IsVisible()))
         {
             // No formatting should be necessary for MustRepaint()!
-            if ( !pParaPortion->IsInvalid() || CreateLines( nPara, nY ) )
+            if (CreateLines(nParagraph, nY))
             {
-                if ( !bGrow && GetTextRanger() )
+                if (!bGrow && GetTextRanger())
                 {
                     // For a change in height all below must be reformatted...
-                    for ( sal_Int32 n = nPara+1; n < 
GetParaPortions().Count(); n++ )
+                    for (sal_Int32 n = nParagraph + 1; n < nParaCount; n++)
                     {
-                        ParaPortion* pPP = GetParaPortions()[n];
-                        pPP->MarkSelectionInvalid( 0 );
-                        pPP->GetLines().Reset();
+                        ParaPortion& rParaPortionToInvalidate = 
maParaPortionList.getRef(n);
+                        rParaPortionToInvalidate.MarkSelectionInvalid(0);
+                        rParaPortionToInvalidate.GetLines().Reset();
                     }
                 }
                 bGrow = true;
-                if ( IsCallParaInsertedOrDeleted() )
+                if (IsCallParaInsertedOrDeleted())
                 {
-                    GetEditEnginePtr()->ParagraphHeightChanged( nPara );
+                    GetEditEnginePtr()->ParagraphHeightChanged(nParagraph);
 
                     for (EditView* pView : aEditViews)
                     {
@@ -447,13 +433,90 @@ void ImpEditEngine::FormatDoc()
                     }
 
                 }
-                pParaPortion->SetMustRepaint( false );
+                rParaPortion.SetMustRepaint(false);
             }
 
-            aRepaintParas.insert(nPara);
+            aRepaintParagraphList.insert(nParagraph);
         }
-        nY += pParaPortion->GetHeight();
+        nY += rParaPortion.GetHeight();
     }
+    return nY;
+}
+
+namespace
+{
+constexpr std::array<ScalingParameters, 13> constScaleLevels =
+{
+    ScalingParameters{100.0, 100.0, 100.0,  90.0 },
+    ScalingParameters{ 92.5,  92.5, 100.0,  90.0 },
+    ScalingParameters{ 92.5,  92.5, 100.0,  80.0 },
+    ScalingParameters{ 85.0,  85.0, 100.0,  90.0 },
+    ScalingParameters{ 85.0,  85.0, 100.0,  80.0 },
+    ScalingParameters{ 77.5,  77.5, 100.0,  80.0 },
+    ScalingParameters{ 70.0,  70.0, 100.0,  80.0 },
+    ScalingParameters{ 62.5,  62.5, 100.0,  80.0 },
+    ScalingParameters{ 55.0,  55.0, 100.0,  80.0 },
+    ScalingParameters{ 47.5,  47.5, 100.0,  80.0 },
+    ScalingParameters{ 40.0,  40.0, 100.0,  80.0 },
+    ScalingParameters{ 32.5,  32.5, 100.0,  80.0 },
+    ScalingParameters{ 25.0,  25.0, 100.0,  80.0 },
+};
+
+} // end anonymous ns
+
+void ImpEditEngine::ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& 
aRepaintParagraphList)
+{
+    if (!maCustomScalingParameters.areValuesDefault())
+        maScalingParameters = maCustomScalingParameters;
+
+    tools::Long nHeight = FormatParagraphs(aRepaintParagraphList);
+    bool bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns);
+
+    size_t nCurrentScaleLevel = 0;
+    while (bOverflow && nCurrentScaleLevel < constScaleLevels.size())
+    {
+        // Clean-up and reset paragraphs
+        aRepaintParagraphList.clear();
+        for (auto& pParaPortionToInvalidate : maParaPortionList)
+        {
+            pParaPortionToInvalidate->GetLines().Reset();
+            pParaPortionToInvalidate->MarkSelectionInvalid(0);
+            pParaPortionToInvalidate->SetMustRepaint(true);
+        }
+
+        // Get new scaling parameters
+        maScalingParameters = constScaleLevels[nCurrentScaleLevel];
+
+        // Try again with different scaling factor
+        nHeight = FormatParagraphs(aRepaintParagraphList);
+        bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns);
+
+        // Increase scale level
+        nCurrentScaleLevel++;
+    }
+}
+
+void ImpEditEngine::FormatDoc()
+{
+    if (!IsUpdateLayout() || IsFormatting())
+        return;
+
+    mbIsFormatting = true;
+
+    // Then I can also start the spell-timer...
+    if (GetStatus().DoOnlineSpelling())
+        StartOnlineSpellTimer();
+
+    // Reserve, as it should match the current number of paragraphs
+    bool bMapChanged = ImpCheckRefMapMode();
+
+    o3tl::sorted_vector<sal_Int32> aRepaintParagraphList;
+    aRepaintParagraphList.reserve(maParaPortionList.Count());
+
+    if (maStatus.DoStretch())
+        ScaleContentToFitWindow(aRepaintParagraphList);
+    else
+        FormatParagraphs(aRepaintParagraphList);
 
     aInvalidRect = tools::Rectangle(); // make empty
 
@@ -493,10 +556,10 @@ void ImpEditEngine::FormatDoc()
             }
         }
 
-        if (!aRepaintParas.empty())
+        if (!aRepaintParagraphList.empty())
         {
             auto CombineRepaintParasAreas = [&](const LineAreaInfo& rInfo) {
-                if (aRepaintParas.count(rInfo.nPortion))
+                if (aRepaintParagraphList.count(rInfo.nPortion))
                     aInvalidRect.Union(rInfo.aArea);
                 return CallbackResult::Continue;
             };
@@ -1015,9 +1078,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, 
sal_uInt32 nStartPosY )
                         if (maStatus.DoStretch() && (fFontScalingX != 100.0))
                             nCurPos = basegfx::fround(double(nCurPos) * 100.0 
/ std::max(fFontScalingX, 1.0));
 
-                        short nAllSpaceBeforeText = static_cast< short 
>(rLRItem.GetTextLeft()/* + rLRItem.GetTextLeft()*/ + 
nSpaceBeforeAndMinLabelWidth);
-                        aCurrentTab.aTabStop = 
pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText 
/*rLRItem.GetTextLeft()*/, maEditDoc.GetDefTab() );
-                        aCurrentTab.nTabPos = 
scaleXFontValue(tools::Long(aCurrentTab.aTabStop.GetTabPos() + 
nAllSpaceBeforeText/*rLRItem.GetTextLeft()*/));
+                        short nAllSpaceBeforeText = 
short(rLRItem.GetTextLeft());
+                        aCurrentTab.aTabStop = 
pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText , 
maEditDoc.GetDefTab() );
+                        aCurrentTab.nTabPos = 
tools::Long(aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText);
                         aCurrentTab.bValid = false;
 
                         // Switch direction in R2L para...
@@ -4470,7 +4533,7 @@ void 
ImpEditEngine::setScalingParameters(ScalingParameters const& rScalingParame
     }
 
     bool bScalingChanged = maScalingParameters != aNewScalingParameters;
-    maScalingParameters = aNewScalingParameters;
+    maCustomScalingParameters = maScalingParameters = aNewScalingParameters;
 
     if (bScalingChanged && maStatus.DoStretch())
     {
diff --git a/include/editeng/editdata.hxx b/include/editeng/editdata.hxx
index 6225ef897b2f..a4a160cc171f 100644
--- a/include/editeng/editdata.hxx
+++ b/include/editeng/editdata.hxx
@@ -282,6 +282,10 @@ struct ScalingParameters
             && fSpacingX == rOther.fSpacingX
             && fSpacingY == rOther.fSpacingY;
     }
+    bool areValuesDefault()
+    {
+        return fFontX == 100.0 && fFontY == 100.0 && fSpacingX == 100.0 && 
fSpacingY == 100.0;
+    }
 };
 
 struct EECharAttrib
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index ccc7dafe822a..8733e4c4d429 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -897,7 +897,7 @@ public:
     /// Set attributes from rSet an all characters of nPara.
     void SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet);
     void            RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich = 0 
);
-    void            QuickFormatDoc();
+    void QuickFormatDoc();
 
     bool            UpdateFields();
     void            RemoveFields( const std::function<bool ( const 
SvxFieldData* )>& isFieldData = [] (const SvxFieldData* ){return true;} );
diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx
index d9c0908e505b..f3c3a300eed7 100644
--- a/include/svx/svdotext.hxx
+++ b/include/svx/svdotext.hxx
@@ -273,9 +273,9 @@ private:
                                        tools::Rectangle&       rAnchorRect,
                                        tools::Rectangle&       rPaintRect,
                                        Fraction&        aFitXCorrection ) 
const;
-    void ImpAutoFitText( SdrOutliner& rOutliner ) const;
-    void ImpAutoFitText( SdrOutliner& rOutliner, const Size& rShapeSize, bool 
bIsVerticalWriting ) const;
-    void autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size& 
rShapeSize, bool bIsVerticalWriting) const;
+
+    void setupAutoFitText( SdrOutliner& rOutliner ) const;
+    void setupAutoFitText(SdrOutliner& rOutliner, const Size& rShapeSize) 
const;
 
     SVX_DLLPRIVATE rtl::Reference<SdrObject> 
ImpConvertContainedTextToSdrPathObjs(bool bToPoly) const;
     SVX_DLLPRIVATE void ImpRegisterLink();
diff --git a/sd/qa/unit/TextFittingTest.cxx b/sd/qa/unit/TextFittingTest.cxx
index e88a2680f005..e4d37c0149bf 100644
--- a/sd/qa/unit/TextFittingTest.cxx
+++ b/sd/qa/unit/TextFittingTest.cxx
@@ -74,16 +74,16 @@ CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest)
     Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pEditEngine->GetParagraphCount());
 
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(87.49, 
pEditEngine->getScalingParameters().fFontY, 1E-2);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(90.0, 
pEditEngine->getScalingParameters().fSpacingY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.5, 
pEditEngine->getScalingParameters().fFontY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(80.0, 
pEditEngine->getScalingParameters().fSpacingY, 1E-2);
 
     // Add paragraph 5
     rEditView.SetSelection(ESelection(4, 0, 4, 0));
     rEditView.InsertText(u"
D5"_ustr);
     CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pEditEngine->GetParagraphCount());
 
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(54.68, 
pEditEngine->getScalingParameters().fFontY, 1E-2);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
pEditEngine->getScalingParameters().fSpacingY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(70.0, 
pEditEngine->getScalingParameters().fFontY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(80.0, 
pEditEngine->getScalingParameters().fSpacingY, 1E-2);
 
     // Add paragraph 6
     rEditView.SetSelection(ESelection(5, 0, 5, 0));
@@ -105,8 +105,8 @@ CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest)
     rEditView.DeleteSelected();
     CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pEditEngine->GetParagraphCount());
 
-    // not ideal - scaling should be 100%, but close enough
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(99.05, 
pEditEngine->getScalingParameters().fFontY, 1E-2);
+    // We are back to 100%
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
pEditEngine->getScalingParameters().fFontY, 1E-2);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
pEditEngine->getScalingParameters().fSpacingY, 1E-2);
 
     // are we still in text edit mode?
diff --git a/sd/qa/unit/data/xml/n593612_0.xml 
b/sd/qa/unit/data/xml/n593612_0.xml
index 3f5f88e445f1..0639294c5007 100644
--- a/sd/qa/unit/data/xml/n593612_0.xml
+++ b/sd/qa/unit/data/xml/n593612_0.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <XShapes>
- <XShape positionX="11429" positionY="1324" sizeX="2259" sizeY="15209" 
type="com.sun.star.drawing.CustomShape" name="Rectangle 52" 
text="&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;"
 fontHeight="24.000000" fontColor="ffffffff" textAutoGrowHeight="true" 
textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" 
textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="254" 
textRightDistance="254" textUpperDistance="127" textLowerDistance="127" 
textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" 
textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" 
textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" 
textAnimationStartInside="false" textAnimationStopInside="false" 
textWritingMode="LR_TB" fillStyle="SOLID" fillColor="3c8c93" 
fillTransparence="0" fillTran
 sparenceGradientName="">
+ <XShape positionX="11429" positionY="1324" sizeX="2259" sizeY="15124" 
type="com.sun.star.drawing.CustomShape" name="Rectangle 52" 
text="&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;"
 fontHeight="24.000000" fontColor="ffffffff" textAutoGrowHeight="true" 
textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" 
textHorizontalAdjust="CENTER" textVerticalAdjust="TOP" textLeftDistance="254" 
textRightDistance="254" textUpperDistance="127" textLowerDistance="127" 
textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" 
textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" 
textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" 
textAnimationStartInside="false" textAnimationStopInside="false" 
textWritingMode="LR_TB" fillStyle="SOLID" fillColor="3c8c93" 
fillTransparence="0" fillTran
 sparenceGradientName="">
   <FillTransparenceGradient style="LINEAR" startColor="000000" 
endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" 
startIntensity="100" endIntensity="100" stepCount="0"/>
   <FillGradient style="LINEAR" startColor="3465a4" endColor="ffffff" angle="0" 
border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" 
stepCount="0"/>
   <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
@@ -10,7 +10,7 @@
   <LineEnd/>
   <Transformation>
    <Line1 column1="2260.000000" column2="0.000000" column3="11429.000000"/>
-   <Line2 column1="0.000000" column2="15210.000000" column3="1324.000000"/>
+   <Line2 column1="0.000000" column2="15125.000000" column3="1324.000000"/>
    <Line3 column1="0.000000" column2="0.000000" column3="1.000000"/>
   </Transformation>
   <CustomShapeGeometry>
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx 
b/sd/qa/unit/export-tests-ooxml3.cxx
index 106073c47816..447f014dbf5e 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -226,7 +226,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testFontScale)
     OUString sScale = getXPath(pXmlDocContent,
                                
"/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:bodyPr/a:normAutofit"_ostr,
                                "fontScale"_ostr);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(81111), sScale.toInt32(), 1000);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(85000), sScale.toInt32(), 1000);
 }
 
 CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testShapeAutofitPPTX)
diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx
index 0f25ce9095a1..986e2c7a4126 100644
--- a/svx/source/svdraw/svdotext.cxx
+++ b/svx/source/svdraw/svdotext.cxx
@@ -1234,14 +1234,14 @@ void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool     
        bContourFrame,
     }
     else if (IsAutoFit())
     {
-        ImpAutoFitText(rOutliner);
+        setupAutoFitText(rOutliner);
     }
 }
 
 double SdrTextObj::GetFontScale() const
 {
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
-    // This eventually calls ImpAutoFitText
+    // This eventually calls setupAutoFitText
     UpdateOutlinerFormatting(rOutliner, o3tl::temporary(tools::Rectangle()));
 
     return rOutliner.getScalingParameters().fFontY;
@@ -1250,133 +1250,41 @@ double SdrTextObj::GetFontScale() const
 double SdrTextObj::GetSpacingScale() const
 {
     SdrOutliner& rOutliner = ImpGetDrawOutliner();
-    // This eventually calls ImpAutoFitText
+    // This eventually calls setupAutoFitText
     UpdateOutlinerFormatting(rOutliner, o3tl::temporary(tools::Rectangle()));
 
     return rOutliner.getScalingParameters().fSpacingY;
 }
 
-void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
+void SdrTextObj::setupAutoFitText(SdrOutliner& rOutliner) const
 {
-    const Size aShapeSize=GetSnapRect().GetSize();
-    ImpAutoFitText( rOutliner,
-                    
Size(aShapeSize.Width()-GetTextLeftDistance()-GetTextRightDistance(),
-                         
aShapeSize.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
-                    IsVerticalWriting() );
-}
+    const Size aShapeSize = GetSnapRect().GetSize();
+    Size aSize(aShapeSize.Width() - GetTextLeftDistance() - 
GetTextRightDistance(),
+               aShapeSize.Height() - GetTextUpperDistance() - 
GetTextLowerDistance());
 
-void SdrTextObj::ImpAutoFitText(SdrOutliner& rOutliner, const Size& rTextSize,
-                                bool bIsVerticalWriting) const
-{
-    autoFitTextForCompatibility(rOutliner, rTextSize, bIsVerticalWriting);
+    setupAutoFitText(rOutliner, aSize);
 }
-
-void SdrTextObj::autoFitTextForCompatibility(SdrOutliner& rOutliner, const 
Size& rTextBoxSize, bool bIsVerticalWriting) const
+void SdrTextObj::setupAutoFitText(SdrOutliner& rOutliner, const Size& 
rTextBoxSize) const
 {
-    rOutliner.setRoundFontSizeToPt(true);
+    rOutliner.setRoundFontSizeToPt(true); // We need to round the font size 
nearest integer pt size
+    rOutliner.SetMaxAutoPaperSize(rTextBoxSize);
+    rOutliner.SetPaperSize(rTextBoxSize);
 
     const SdrTextFitToSizeTypeItem& rItem = 
GetObjectItem(SDRATTR_TEXT_FITTOSIZE);
-    double fMaxScale = rItem.getFontScale();
-    if (fMaxScale > 0.0)
-    {
-        rOutliner.setScalingParameters({ fMaxScale, fMaxScale, 100.0, 100.0 });
-    }
-    else
-    {
-        fMaxScale = 100.0;
-    }
-
-    Size aCurrentTextBoxSize = rOutliner.CalcTextSizeNTP();
-    if (aCurrentTextBoxSize.Height() == 0)
-        return;
 
-    tools::Long nExtendTextBoxBy = -50;
-    aCurrentTextBoxSize.extendBy(0, nExtendTextBoxBy);
-    double fCurrentFitFactor = 1.0;
+    double fFontScale = rItem.getFontScale();
+    double fSpacingScale = rItem.getSpacingScale();
 
-    if (bIsVerticalWriting)
-        fCurrentFitFactor = double(rTextBoxSize.Width()) / 
aCurrentTextBoxSize.Width();
-    else
-        fCurrentFitFactor = double(rTextBoxSize.Height()) / 
aCurrentTextBoxSize.Height();
-
-    auto aParameters = rOutliner.getScalingParameters();
-    double fInitialFontScaleY = aParameters.fFontY;
-    double fInitialSpacing = aParameters.fSpacingY;
-
-    if (fCurrentFitFactor >= 1.0 && fInitialFontScaleY >= 100.0 && 
fInitialSpacing >= 100.0)
-        return;
-
-    sal_Int32 nFontHeight = 
GetObjectItemSet().Get(EE_CHAR_FONTHEIGHT).GetHeight();
-
-    double fFontHeightPt = o3tl::convert(double(nFontHeight), 
o3tl::Length::mm100, o3tl::Length::pt);
-    double fMinY = 0.0;
-    double fMaxY = fMaxScale;
-
-    double fBestFontScale = 0.0;
-    double fBestSpacing = 100.0;
-    double fBestFitFactor = fCurrentFitFactor;
-
-    if (fCurrentFitFactor >= 1.0)
+    if (fFontScale > 0.0 && fSpacingScale > 0.0 && !mbInEditMode)
     {
-        fMinY = fInitialFontScaleY;
-        fBestFontScale = fInitialFontScaleY;
-        fBestSpacing = fInitialSpacing;
-        fBestFitFactor = fCurrentFitFactor;
+        rOutliner.setScalingParameters({ fFontScale, fFontScale, 100.0, 
fSpacingScale });
     }
     else
     {
-        fMaxY = std::min(fInitialFontScaleY, fMaxScale);
+        rOutliner.resetScalingParameters();
     }
 
-    double fInTheMidle = 0.5;
-
-    int iteration = 0;
-    double fFitFactorTarget = 1.00;
-
-    while (iteration < 10)
-    {
-        iteration++;
-        double fScaleY = fMinY + (fMaxY - fMinY) * fInTheMidle;
-
-        double fScaledFontHeight = fFontHeightPt * (fScaleY / 100.0);
-        double fRoundedScaledFontHeight = std::floor(fScaledFontHeight * 10.0) 
/ 10.0;
-        double fCurrentFontScale = (fRoundedScaledFontHeight / fFontHeightPt) 
* 100.0;
-
-        fCurrentFitFactor = 0.0; // reset fit factor;
-
-        for (double fCurrentSpacing : {100.0, 90.0, 80.0})
-        {
-            if (fCurrentFitFactor >= fFitFactorTarget)
-                continue;
-
-            rOutliner.setScalingParameters({ fCurrentFontScale, 
fCurrentFontScale, 100.0, fCurrentSpacing });
-
-            aCurrentTextBoxSize = rOutliner.CalcTextSizeNTP();
-            aCurrentTextBoxSize.extendBy(0, nExtendTextBoxBy);
-            if (bIsVerticalWriting)
-                fCurrentFitFactor = double(rTextBoxSize.Width()) / 
aCurrentTextBoxSize.Width();
-            else
-                fCurrentFitFactor = double(rTextBoxSize.Height()) / 
aCurrentTextBoxSize.Height();
-
-
-            if (fCurrentSpacing == 100.0)
-            {
-                if (fCurrentFitFactor > fFitFactorTarget)
-                    fMinY = fCurrentFontScale;
-                else
-                    fMaxY = fCurrentFontScale;
-            }
-
-            if ((fBestFitFactor < fFitFactorTarget && fCurrentFitFactor > 
fBestFitFactor)
-            ||  (fCurrentFitFactor >= fFitFactorTarget && fCurrentFitFactor < 
fBestFitFactor))
-            {
-                fBestFontScale = fCurrentFontScale;
-                fBestSpacing = fCurrentSpacing;
-                fBestFitFactor = fCurrentFitFactor;
-            }
-        }
-    }
-    rOutliner.setScalingParameters({ fBestFontScale, fBestFontScale, 100.0, 
fBestSpacing });
+    rOutliner.QuickFormatDoc();
 }
 
 void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, 
tools::Rectangle& rPaintRect ) const
@@ -1967,10 +1875,13 @@ void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* 
pEditStatus )
         assert(mpEditingOutliner);
         mbInDownScale = true;
 
+        // Need to reset scaling so it searches for the fitting size again
+        mpEditingOutliner->resetScalingParameters();
+
         // sucks that we cannot disable paints via
         // mpEditingOutliner->SetUpdateMode(FALSE) - but EditEngine skips
         // formatting as well, then.
-        ImpAutoFitText(*mpEditingOutliner);
+        setupAutoFitText(*mpEditingOutliner);
         mbInDownScale = false;
     }
 }
diff --git a/svx/source/svdraw/svdotextdecomposition.cxx 
b/svx/source/svdraw/svdotextdecomposition.cxx
index 84f440b81121..5a9abfe654b3 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -937,11 +937,11 @@ void SdrTextObj::impDecomposeAutoFitTextPrimitive(
         rOutliner.SetMinColumnWrapHeight(nAnchorTextWidth);
     }
 
-    rOutliner.SetPaperSize(aNullSize);
+    rOutliner.SetPaperSize(aAnchorTextSize);
     rOutliner.SetUpdateLayout(true);
     rOutliner.SetText(*pOutlinerParaObject);
-    ImpAutoFitText(rOutliner,aAnchorTextSize,bVerticalWriting);
 
+    setupAutoFitText(rOutliner, aAnchorTextSize);
     // set visualizing page at Outliner; needed e.g. for PageNumberField 
decomposition
     
rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage()));
 
diff --git a/svx/source/svdraw/svdotxed.cxx b/svx/source/svdraw/svdotxed.cxx
index 120bf26b1751..8666f262be92 100644
--- a/svx/source/svdraw/svdotxed.cxx
+++ b/svx/source/svdraw/svdotxed.cxx
@@ -110,7 +110,7 @@ bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl)
     }
     else if (IsAutoFit())
     {
-        ImpAutoFitText(rOutl);
+        setupAutoFitText(rOutl);
     }
 
     if(pOutlinerParaObject)

Reply via email to