editeng/source/editeng/impedit.hxx                 |    9 +
 editeng/source/editeng/impedit2.cxx                |   22 +++
 editeng/source/editeng/impedit3.cxx                |  124 ++++++++++++++-----
 include/editeng/editdata.hxx                       |    4 
 include/editeng/outliner.hxx                       |    2 
 include/svl/solar.hrc                              |    2 
 include/svx/sdtfsitm.hxx                           |   13 +-
 include/svx/svdotext.hxx                           |    6 
 include/svx/unoshprp.hxx                           |   16 +-
 oox/inc/drawingml/textbodyproperties.hxx           |    1 
 oox/source/drawingml/diagram/diagram.cxx           |   21 ++-
 oox/source/drawingml/textbodypropertiescontext.cxx |    5 
 oox/source/token/properties.txt                    |    2 
 sd/qa/unit/TextFittingTest.cxx                     |   12 -
 sd/qa/unit/data/xml/n593612_0.xml                  |    4 
 sd/qa/unit/export-tests-ooxml2.cxx                 |   16 +-
 sd/qa/unit/export-tests-ooxml3.cxx                 |    2 
 sd/qa/unit/import-tests-smartart.cxx               |   15 +-
 sd/qa/unit/import-tests2.cxx                       |    6 
 svx/source/svdraw/svdattr.cxx                      |    5 
 svx/source/svdraw/svdotext.cxx                     |  133 +++------------------
 svx/source/svdraw/svdotextdecomposition.cxx        |    4 
 svx/source/svdraw/svdotxed.cxx                     |    2 
 svx/source/unodraw/unoshape.cxx                    |   48 +++++--
 24 files changed, 261 insertions(+), 213 deletions(-)

New commits:
commit f61ea135430d7b4a1fac7de1e57a1314fbb1b49e
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Mar 28 12:30:34 2024 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Wed Apr 3 04:06:50 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 <[email protected]>

diff --git a/editeng/source/editeng/impedit.hxx 
b/editeng/source/editeng/impedit.hxx
index a694196dbade..e09712f74bad 100644
--- a/editeng/source/editeng/impedit.hxx
+++ b/editeng/source/editeng/impedit.hxx
@@ -571,6 +571,7 @@ private:
 
     Color               maBackgroundColor;
 
+    ScalingParameters maCustomScalingParameters;
     ScalingParameters maScalingParameters;
     bool mbRoundToNearestPt;
 
@@ -657,6 +658,7 @@ private:
     void                ParaAttribsChanged( ContentNode const * pNode, bool 
bIgnoreUndoCheck = false );
     void                TextModified();
     void                CalcHeight(ParaPortion& rParaPortion);
+    bool isInEmptyClusterAtTheEnd(ParaPortion& rParaPortion);
 
     void                InsertUndo( std::unique_ptr<EditUndo> pUndo, bool 
bTryMerge = false );
     void                ResetUndoManager();
@@ -977,8 +979,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 d3f07cec65ed..da4d851b3315 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -4388,12 +4388,31 @@ tools::Long ImpEditEngine::GetXPos(ParaPortion const& 
rParaPortion, EditLine con
     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& rPortion)
 {
     rPortion.mnHeight = 0;
     rPortion.mnFirstLineOffset = 0;
 
-    if (!rPortion.IsVisible())
+    if (!rPortion.IsVisible() || isInEmptyClusterAtTheEnd(rPortion))
         return;
 
     OSL_ENSURE(rPortion.GetLines().Count(), "Paragraph with no lines in 
ParaPortion::CalcHeight");
@@ -4428,7 +4447,6 @@ void ImpEditEngine::CalcHeight(ParaPortion& rPortion)
         rPortion.mnHeight += 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 821e345a1b05..a2dee889aa63 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -398,47 +398,34 @@ void ImpEditEngine::FormatFullDoc()
     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 = GetParaPortions().Count();
     tools::Long nY = 0;
     bool bGrow = false;
 
-    // Here already, so that not always in CreateLines...
-    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& rParaPortion = GetParaPortions().getRef(nPara);
+        ParaPortion& rParaPortion = GetParaPortions().getRef(nParagraph);
         if (rParaPortion.MustRepaint() || (rParaPortion.IsInvalid() && 
rParaPortion.IsVisible()))
         {
             // No formatting should be necessary for MustRepaint()!
-            if (!rParaPortion.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& rParaPortionToInvalidate = 
GetParaPortions().getRef(n);
-                        rParaPortionToInvalidate.MarkSelectionInvalid( 0 );
+                        rParaPortionToInvalidate.MarkSelectionInvalid(0);
                         rParaPortionToInvalidate.GetLines().Reset();
                     }
                 }
                 bGrow = true;
-                if ( IsCallParaInsertedOrDeleted() )
+                if (IsCallParaInsertedOrDeleted())
                 {
-                    GetEditEnginePtr()->ParagraphHeightChanged( nPara );
+                    GetEditEnginePtr()->ParagraphHeightChanged(nParagraph);
 
                     for (EditView* pView : maEditViews)
                     {
@@ -446,13 +433,88 @@ void ImpEditEngine::FormatDoc()
                     }
 
                 }
-                rParaPortion.SetMustRepaint( false );
+                rParaPortion.SetMustRepaint(false);
             }
 
-            aRepaintParas.insert(nPara);
+            aRepaintParagraphList.insert(nParagraph);
         }
         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 : GetParaPortions())
+        {
+            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
+    o3tl::sorted_vector<sal_Int32> aRepaintParagraphList;
+    aRepaintParagraphList.reserve(GetParaPortions().Count());
+
+    if (maStatus.DoStretch())
+        ScaleContentToFitWindow(aRepaintParagraphList);
+    else
+        FormatParagraphs(aRepaintParagraphList);
 
     maInvalidRect = tools::Rectangle(); // make empty
 
@@ -491,10 +553,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))
                     maInvalidRect.Union(rInfo.aArea);
                 return CallbackResult::Continue;
             };
@@ -1010,9 +1072,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...
@@ -4542,7 +4604,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 6c8e5abe2db7..0985e53a1b96 100644
--- a/include/editeng/editdata.hxx
+++ b/include/editeng/editdata.hxx
@@ -170,6 +170,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 e0d14487ea13..fee0b98a26a0 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -899,7 +899,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 
);
-    SAL_DLLPRIVATE 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 84aea85fdeff..aeb99556f097 100644
--- a/include/svx/svdotext.hxx
+++ b/include/svx/svdotext.hxx
@@ -274,9 +274,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 5a9c37730e69..13f41ff793db 100644
--- a/sd/qa/unit/TextFittingTest.cxx
+++ b/sd/qa/unit/TextFittingTest.cxx
@@ -73,16 +73,16 @@ CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest)
     Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT_EQUAL(sal_Int32(4), rEditEngine.GetParagraphCount());
 
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(87.49, 
rEditEngine.getScalingParameters().fFontY, 1E-2);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(90.0, 
rEditEngine.getScalingParameters().fSpacingY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.5, 
rEditEngine.getScalingParameters().fFontY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(80.0, 
rEditEngine.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), rEditEngine.GetParagraphCount());
 
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(54.68, 
rEditEngine.getScalingParameters().fFontY, 1E-2);
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
rEditEngine.getScalingParameters().fSpacingY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(70.0, 
rEditEngine.getScalingParameters().fFontY, 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(80.0, 
rEditEngine.getScalingParameters().fSpacingY, 1E-2);
 
     // Add paragraph 6
     rEditView.SetSelection(ESelection(5, 0, 5, 0));
@@ -104,8 +104,8 @@ CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest)
     rEditView.DeleteSelected();
     CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rEditEngine.GetParagraphCount());
 
-    // not ideal - scaling should be 100%, but close enough
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(99.05, 
rEditEngine.getScalingParameters().fFontY, 1E-2);
+    // We are back to 100%
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
rEditEngine.getScalingParameters().fFontY, 1E-2);
     CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
rEditEngine.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 a64f90df8dd6..f9b8bba3eebc 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 8e5e1f835542..526b4d8b0b8e 100644
--- a/svx/source/svdraw/svdotext.cxx
+++ b/svx/source/svdraw/svdotext.cxx
@@ -1233,14 +1233,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;
@@ -1249,133 +1249,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
@@ -1966,10 +1874,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 e54fdfd76cd7..7b94bfbc1093 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -935,11 +935,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)
commit db64748f1ee771da9da857f95601b9e08b577166
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Mon Apr 1 20:32:15 2024 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Wed Apr 3 04:06:39 2024 +0200

    svx: read font and spacing scaling from oox, add bot as UNO prop.
    
    - Read spacing in oox.
    - Add spacing scaling as a property.
    - Rename property "TextFitToSizeScale" to "TextFitToSizeFontScale"
    - Add property "TextFitToSizeSpacingScale"
    
    Change-Id: Icde575e55a3146169d86bb538a57adcf1fa228a7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165633
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <[email protected]>

diff --git a/include/svl/solar.hrc b/include/svl/solar.hrc
index a3a0ecd0ac0d..288c3073caa0 100644
--- a/include/svl/solar.hrc
+++ b/include/svl/solar.hrc
@@ -23,7 +23,7 @@
 // defines ------------------------------------------------------------------
 
 #define OWN_ATTR_VALUE_START                    3900
-#define OWN_ATTR_VALUE_END                      4009
+#define OWN_ATTR_VALUE_END                      4020
 
 #define RID_LIB_START               10000
 #define RID_LIB_END                 19999
diff --git a/include/svx/sdtfsitm.hxx b/include/svx/sdtfsitm.hxx
index ccdcb7c4dbe9..55fe48a5fc61 100644
--- a/include/svx/sdtfsitm.hxx
+++ b/include/svx/sdtfsitm.hxx
@@ -42,7 +42,8 @@ public:
 
     SdrTextFitToSizeTypeItem(const SdrTextFitToSizeTypeItem& rItem)
         : SfxEnumItem(rItem)
-        , m_nMaxScale(rItem.GetMaxScale())
+        , mfFontScale(rItem.getFontScale())
+        , mfSpacingScale(rItem.getSpacingScale())
     {
     }
 
@@ -59,10 +60,14 @@ public:
     virtual bool             GetBoolValue() const override;
     virtual void             SetBoolValue(bool bVal) override;
 
-    void SetMaxScale(double nMaxScale) { m_nMaxScale = nMaxScale; }
-    double GetMaxScale() const { return m_nMaxScale; }
+    void setFontScale(double fScale) { mfFontScale = fScale; }
+    double getFontScale() const { return mfFontScale; }
+
+    void setSpacingScale(double fScale) { mfSpacingScale = fScale; }
+    double getSpacingScale() const { return mfSpacingScale; }
 private:
-    double m_nMaxScale = 0.0;
+    double mfFontScale = 0.0;
+    double mfSpacingScale = 0.0;
 };
 
 #endif
diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx
index 9244f719a684..c4fdfafacb2a 100644
--- a/include/svx/unoshprp.hxx
+++ b/include/svx/unoshprp.hxx
@@ -193,12 +193,13 @@
 #define OWN_ATTR_SIGNATURELINE_UNSIGNED_IMAGE   (OWN_ATTR_VALUE_START+102)
 #define OWN_ATTR_SIGNATURELINE_IS_SIGNED        (OWN_ATTR_VALUE_START+103)
 #define OWN_ATTR_QRCODE                         (OWN_ATTR_VALUE_START+104)
-#define OWN_ATTR_TEXTFITTOSIZESCALE             (OWN_ATTR_VALUE_START+105)
-#define OWN_ATTR_TEXTCOLUMNS                    (OWN_ATTR_VALUE_START+106)
-#define OWN_ATTR_HYPERLINK                      (OWN_ATTR_VALUE_START+107)
-#define OWN_ATTR_MISC_OBJ_DECORATIVE            (OWN_ATTR_VALUE_START+108)
-#define OWN_ATTR_OBJ_ISEMPTYPRESOBJ             (OWN_ATTR_VALUE_START+109)
-// ATTENTION: current maximum is OWN_ATTR_VALUE_START+109 svx; when adding 
values, update
+#define OWN_ATTR_TEXTFITTOSIZE_FONT_SCALE       (OWN_ATTR_VALUE_START+105)
+#define OWN_ATTR_TEXTFITTOSIZE_SPACING_SCALE    (OWN_ATTR_VALUE_START+106)
+#define OWN_ATTR_TEXTCOLUMNS                    (OWN_ATTR_VALUE_START+107)
+#define OWN_ATTR_HYPERLINK                      (OWN_ATTR_VALUE_START+108)
+#define OWN_ATTR_MISC_OBJ_DECORATIVE            (OWN_ATTR_VALUE_START+109)
+#define OWN_ATTR_OBJ_ISEMPTYPRESOBJ             (OWN_ATTR_VALUE_START+110)
+// ATTENTION: current maximum is OWN_ATTR_VALUE_START+120 svx; when adding 
values, update
 // OWN_ATTR_VALUE_END in include/svl/solar.hrc accordingly
 
 // #FontWork#
@@ -367,7 +368,8 @@
     { UNO_NAME_MISC_OBJ_SIZEPROTECT,  SDRATTR_OBJSIZEPROTECT          , 
cppu::UnoType<bool>::get(),                      0,  0},\
     { u"UINameSingular"_ustr,          OWN_ATTR_UINAME_SINGULAR        , 
::cppu::UnoType<OUString>::get(),    css::beans::PropertyAttribute::READONLY,   
0}, \
     { u"UINamePlural"_ustr,            OWN_ATTR_UINAME_PLURAL          , 
::cppu::UnoType<OUString>::get(),    css::beans::PropertyAttribute::READONLY,   
0}, \
-    { u"TextFitToSizeScale"_ustr, OWN_ATTR_TEXTFITTOSIZESCALE, 
::cppu::UnoType<double>::get(), 0, 0}, \
+    { u"TextFitToSizeFontScale"_ustr, OWN_ATTR_TEXTFITTOSIZE_FONT_SCALE, 
::cppu::UnoType<double>::get(), 0, 0}, \
+    { u"TextFitToSizeSpacingScale"_ustr, OWN_ATTR_TEXTFITTOSIZE_SPACING_SCALE, 
::cppu::UnoType<double>::get(), 0, 0}, \
     /* #i68101# */ \
     { UNO_NAME_MISC_OBJ_TITLE,        OWN_ATTR_MISC_OBJ_TITLE         , 
::cppu::UnoType<OUString>::get(),    0,  0}, \
     { UNO_NAME_MISC_OBJ_DESCRIPTION,  OWN_ATTR_MISC_OBJ_DESCRIPTION   , 
::cppu::UnoType<OUString>::get(),    0,  0}, \
diff --git a/oox/inc/drawingml/textbodyproperties.hxx 
b/oox/inc/drawingml/textbodyproperties.hxx
index d935f940638d..46cf99614c56 100644
--- a/oox/inc/drawingml/textbodyproperties.hxx
+++ b/oox/inc/drawingml/textbodyproperties.hxx
@@ -50,6 +50,7 @@ struct TextBodyProperties
     OUString                                        msPrst;
     /// Normal autofit: font scale (default: 100%).
     sal_Int32 mnFontScale = 100000;
+    sal_Int32 mnSpacingScale = 100000;
     OUString msHorzOverflow;
     std::optional< sal_Int32 > moVertOverflow{};
 
diff --git a/oox/source/drawingml/diagram/diagram.cxx 
b/oox/source/drawingml/diagram/diagram.cxx
index 029c2c56e962..f63185549c23 100644
--- a/oox/source/drawingml/diagram/diagram.cxx
+++ b/oox/source/drawingml/diagram/diagram.cxx
@@ -185,30 +185,37 @@ void Diagram::syncDiagramFontHeights()
     {
         // Find out the minimum scale within this group.
         const ShapePairs& rShapePairs = rNameAndPairs.second;
-        double nMinScale = 100.0;
+        double fMinFontScale = 100.0;
+        double fMinSpacingScale = 100.0;
         for (const auto& rShapePair : rShapePairs)
         {
             uno::Reference<beans::XPropertySet> 
xPropertySet(rShapePair.second, uno::UNO_QUERY);
             if (xPropertySet.is())
             {
-                double nTextFitToSizeScale = 0.0;
-                xPropertySet->getPropertyValue("TextFitToSizeScale") >>= 
nTextFitToSizeScale;
-                if (nTextFitToSizeScale > 0 && nTextFitToSizeScale < nMinScale)
+                double fFontScale = 0.0;
+                double fSpacingScale = 0.0;
+                xPropertySet->getPropertyValue("TextFitToSizeFontScale") >>= 
fFontScale;
+                xPropertySet->getPropertyValue("TextFitToSizeSpacingScale") 
>>= fSpacingScale;
+
+                if (fFontScale > 0 && fSpacingScale > 0
+                    && (fFontScale < fMinFontScale || (fFontScale == 
fMinFontScale && fSpacingScale < fMinSpacingScale)))
                 {
-                    nMinScale = nTextFitToSizeScale;
+                    fMinFontScale = fFontScale;
+                    fMinSpacingScale = fSpacingScale;
                 }
             }
         }
 
         // Set that minimum scale for all members of the group.
-        if (nMinScale < 100.0)
+        if (fMinFontScale < 100.0 || fMinSpacingScale < 100.0)
         {
             for (const auto& rShapePair : rShapePairs)
             {
                 uno::Reference<beans::XPropertySet> 
xPropertySet(rShapePair.second, uno::UNO_QUERY);
                 if (xPropertySet.is())
                 {
-                    xPropertySet->setPropertyValue("TextFitToSizeScale", 
uno::Any(nMinScale));
+                    xPropertySet->setPropertyValue("TextFitToSizeFontScale", 
uno::Any(fMinFontScale));
+                    
xPropertySet->setPropertyValue("TextFitToSizeSpacingScale", 
uno::Any(fMinSpacingScale));
                 }
             }
         }
diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx 
b/oox/source/drawingml/textbodypropertiescontext.cxx
index a08ae8fb9f6d..598bee8daa4e 100644
--- a/oox/source/drawingml/textbodypropertiescontext.cxx
+++ b/oox/source/drawingml/textbodypropertiescontext.cxx
@@ -237,8 +237,11 @@ ContextHandlerRef 
TextBodyPropertiesContext::onCreateContext( sal_Int32 aElement
             case A_TOKEN( normAutofit ):    // CT_TextNormalAutofit
             {
                 mrTextBodyProp.maPropertyMap.setProperty( PROP_TextFitToSize, 
TextFitToSizeType_AUTOFIT);
-                mrTextBodyProp.maPropertyMap.setProperty( 
PROP_TextAutoGrowHeight, false);
+                
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextAutoGrowHeight, false);
                 mrTextBodyProp.mnFontScale = 
rAttribs.getInteger(XML_fontScale, 100000);
+                mrTextBodyProp.mnSpacingScale = 
rAttribs.getInteger(XML_lnSpcReduction, 100000);
+                
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextFitToSizeFontScale, 
double(mrTextBodyProp.mnFontScale) / 1000.0);
+                
mrTextBodyProp.maPropertyMap.setProperty(PROP_TextFitToSizeSpacingScale, 100.0 
- double(mrTextBodyProp.mnSpacingScale) / 1000.0);
                 break;
             }
             case A_TOKEN( spAutoFit ):
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index 5a0e84708fe3..fd78234fbd0e 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -585,6 +585,8 @@ TextColor
 TextColumns
 TextContourFrame
 TextFitToSize
+TextFitToSizeFontScale
+TextFitToSizeSpacingScale
 TextFrames
 TextHorizontalAdjust
 TextLeftDistance
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx 
b/sd/qa/unit/export-tests-ooxml2.cxx
index ddd272752859..4abd5859aa7d 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -1888,10 +1888,10 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, 
testTextColumns_3columns)
         CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(300)),
                              xColProps->getPropertyValue("AutomaticDistance"));
         // Scale value may be unstable; just test that the text is actually 
scaled
-        double fScale;
-        CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeScale") >>= 
fScale);
-        CPPUNIT_ASSERT_GREATER(0.0, fScale);
-        CPPUNIT_ASSERT_LESS(100.0, fScale);
+        double fFontScale;
+        CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeFontScale") >>= 
fFontScale);
+        CPPUNIT_ASSERT_GREATER(0.0, fFontScale);
+        CPPUNIT_ASSERT_LESS(100.0, fFontScale);
     }
 
     save("Impress Office Open XML");
@@ -1908,10 +1908,10 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, 
testTextColumns_3columns)
         CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(300)),
                              xColProps->getPropertyValue("AutomaticDistance"));
         // Scale value may be unstable; just test that the text is actually 
scaled
-        double fScale;
-        CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeScale") >>= 
fScale);
-        CPPUNIT_ASSERT_GREATER(0.0, fScale);
-        CPPUNIT_ASSERT_LESS(100.0, fScale);
+        double fFontScale;
+        CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeFontScale") >>= 
fFontScale);
+        CPPUNIT_ASSERT_GREATER(0.0, fFontScale);
+        CPPUNIT_ASSERT_LESS(100.0, fFontScale);
     }
 
     xmlDocUniquePtr pXmlDocRels = parseExport("ppt/slides/slide1.xml");
diff --git a/sd/qa/unit/import-tests-smartart.cxx 
b/sd/qa/unit/import-tests-smartart.cxx
index 568f0a90efca..84882fba0e79 100644
--- a/sd/qa/unit/import-tests-smartart.cxx
+++ b/sd/qa/unit/import-tests-smartart.cxx
@@ -1527,21 +1527,22 @@ CPPUNIT_TEST_FIXTURE(SdImportTestSmartArt, 
testAutofitSync)
     uno::Reference<drawing::XShape> xMiddle = getChildShape(xDiagram, 2);
     uno::Reference<beans::XPropertySet> 
xFirstInner(getChildShape(getChildShape(xMiddle, 0), 0),
                                                     uno::UNO_QUERY);
-    double nFirstScale = 0;
-    CPPUNIT_ASSERT(xFirstInner->getPropertyValue("TextFitToSizeScale") >>= 
nFirstScale);
-    CPPUNIT_ASSERT_GREATER(0.0, nFirstScale);
-    CPPUNIT_ASSERT_LESS(100.0, nFirstScale);
+    double fFirstScale = 0;
+    CPPUNIT_ASSERT(xFirstInner->getPropertyValue("TextFitToSizeFontScale") >>= 
fFirstScale);
+    CPPUNIT_ASSERT_GREATER(0.0, fFirstScale);
+    CPPUNIT_ASSERT_LESS(100.0, fFirstScale);
+
     uno::Reference<beans::XPropertySet> 
xSecondInner(getChildShape(getChildShape(xMiddle, 2), 0),
                                                      uno::UNO_QUERY);
-    double nSecondScale = 0;
-    CPPUNIT_ASSERT(xSecondInner->getPropertyValue("TextFitToSizeScale") >>= 
nSecondScale);
+    double fSecondScale = 0;
+    CPPUNIT_ASSERT(xSecondInner->getPropertyValue("TextFitToSizeFontScale") 
>>= fSecondScale);
 
     // Without the accompanying fix in place, this test would have failed with:
     // - Expected: 56
     // - Actual  : 100
     // i.e. the left shape had no scale-down and the right shape was scaled 
down, even if it was
     // requested that their scaling matches.
-    CPPUNIT_ASSERT_EQUAL(nSecondScale, nFirstScale);
+    CPPUNIT_ASSERT_EQUAL(fSecondScale, fFirstScale);
 
     // Without the accompanying fix in place, this test would have failed with:
     // - Expected: 0 (drawing::TextFitToSizeType_NONE)
diff --git a/sd/qa/unit/import-tests2.cxx b/sd/qa/unit/import-tests2.cxx
index 9ade40ad1917..5457224bd642 100644
--- a/sd/qa/unit/import-tests2.cxx
+++ b/sd/qa/unit/import-tests2.cxx
@@ -1368,9 +1368,9 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf120028)
     xPropSet->getPropertyValue("CharHeight") >>= fCharHeight;
     CPPUNIT_ASSERT_DOUBLES_EQUAL(13.5, fCharHeight, 1E-12);
 
-    double fTextSclale = 0.0;
-    xShape->getPropertyValue("TextFitToSizeScale") >>= fTextSclale;
-    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.0, fTextSclale, 1E1);
+    double fFontScale = 0.0;
+    xShape->getPropertyValue("TextFitToSizeFontScale") >>= fFontScale;
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.0, fFontScale, 1E1);
 }
 
 CPPUNIT_TEST_FIXTURE(SdImportTest2, testDescriptionImport)
diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx
index 19a55c3e810a..914503304bad 100644
--- a/svx/source/svdraw/svdattr.cxx
+++ b/svx/source/svdraw/svdattr.cxx
@@ -1134,8 +1134,9 @@ bool SdrTextFitToSizeTypeItem::operator==(const 
SfxPoolItem& rItem) const
     {
         return false;
     }
-
-    return m_nMaxScale == static_cast<const 
SdrTextFitToSizeTypeItem&>(rItem).m_nMaxScale;
+    auto& rTextFitToSizeTypeItem = static_cast<const 
SdrTextFitToSizeTypeItem&>(rItem);
+    return mfFontScale == rTextFitToSizeTypeItem.mfFontScale
+        && mfSpacingScale == rTextFitToSizeTypeItem.mfSpacingScale;
 }
 
 sal_uInt16 SdrTextFitToSizeTypeItem::GetValueCount() const { return 4; }
diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx
index 1a2c28b627f9..8e5e1f835542 100644
--- a/svx/source/svdraw/svdotext.cxx
+++ b/svx/source/svdraw/svdotext.cxx
@@ -1275,7 +1275,7 @@ void SdrTextObj::autoFitTextForCompatibility(SdrOutliner& 
rOutliner, const Size&
     rOutliner.setRoundFontSizeToPt(true);
 
     const SdrTextFitToSizeTypeItem& rItem = 
GetObjectItem(SDRATTR_TEXT_FITTOSIZE);
-    double fMaxScale = rItem.GetMaxScale();
+    double fMaxScale = rItem.getFontScale();
     if (fMaxScale > 0.0)
     {
         rOutliner.setScalingParameters({ fMaxScale, fMaxScale, 100.0, 100.0 });
diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx
index 12bd86564261..108ded54426b 100644
--- a/svx/source/unodraw/unoshape.cxx
+++ b/svx/source/unodraw/unoshape.cxx
@@ -137,22 +137,22 @@ namespace {
 
 
 /// Calculates what scaling factor will be used for autofit text scaling of 
this shape.
-double GetTextFitToSizeScale(SdrObject* pObject)
+SdrTextObj* getTextObjectWithFitToSize(SdrObject* pObject)
 {
     SdrTextObj* pTextObj = DynCastSdrTextObj(pObject);
     if (!pTextObj)
     {
-        return 0;
+        return nullptr;
     }
 
     const SfxItemSet& rTextObjSet = pTextObj->GetMergedItemSet();
     if 
(rTextObjSet.GetItem<SdrTextFitToSizeTypeItem>(SDRATTR_TEXT_FITTOSIZE)->GetValue()
         != drawing::TextFitToSizeType_AUTOFIT)
     {
-        return 0;
+        return nullptr;
     }
 
-    return pTextObj->GetFontScale();
+    return pTextObj;
 }
 }
 
@@ -2331,13 +2331,26 @@ bool SvxShape::setPropertyValueImpl( const OUString&, 
const SfxItemPropertyMapEn
         break;
     }
 
-    case OWN_ATTR_TEXTFITTOSIZESCALE:
+    case OWN_ATTR_TEXTFITTOSIZE_FONT_SCALE:
     {
-        double nMaxScale = 0.0;
-        if (rValue >>= nMaxScale)
+        double fScale = 0.0;
+        if (rValue >>= fScale)
         {
             SdrTextFitToSizeTypeItem 
aItem(pSdrObject->GetMergedItem(SDRATTR_TEXT_FITTOSIZE));
-            aItem.SetMaxScale(nMaxScale);
+            aItem.setFontScale(fScale);
+            pSdrObject->SetMergedItem(aItem);
+            return true;
+        }
+        break;
+    }
+
+    case OWN_ATTR_TEXTFITTOSIZE_SPACING_SCALE:
+    {
+        double fScale = 0.0;
+        if (rValue >>= fScale)
+        {
+            SdrTextFitToSizeTypeItem 
aItem(pSdrObject->GetMergedItem(SDRATTR_TEXT_FITTOSIZE));
+            aItem.setSpacingScale(fScale);
             pSdrObject->SetMergedItem(aItem);
             return true;
         }
@@ -2858,10 +2871,23 @@ bool SvxShape::getPropertyValueImpl( const OUString&, 
const SfxItemPropertyMapEn
         break;
     }
 
-    case OWN_ATTR_TEXTFITTOSIZESCALE:
+    case OWN_ATTR_TEXTFITTOSIZE_FONT_SCALE:
     {
-        double nScale = GetTextFitToSizeScale(GetSdrObject());
-        rValue <<= nScale;
+        auto* pTextObject = getTextObjectWithFitToSize(GetSdrObject());
+        if (pTextObject)
+        {
+            rValue <<= pTextObject->GetFontScale();
+        }
+        break;
+    }
+
+    case OWN_ATTR_TEXTFITTOSIZE_SPACING_SCALE:
+    {
+        auto* pTextObject = getTextObjectWithFitToSize(GetSdrObject());
+        if (pTextObject)
+        {
+            rValue <<= pTextObject->GetSpacingScale();
+        }
         break;
     }
 

Reply via email to