editeng/source/editeng/editeng.cxx     |   16 +++
 include/editeng/editeng.hxx            |    5 -
 sd/CppunitTest_sd_textfitting_tests.mk |   79 ++++++++++++++++
 sd/Module_sd.mk                        |    1 
 sd/qa/unit/TextFittingTest.cxx         |  154 +++++++++++++++++++++++++++++++++
 sd/qa/unit/data/TextFitting.odp        |binary
 svx/source/svdraw/svdotext.cxx         |   20 +++-
 7 files changed, 272 insertions(+), 3 deletions(-)

New commits:
commit 6c042848b688f64b3c56d65dd9dc5fe85412660a
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri May 5 15:34:38 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Sat May 6 14:38:32 2023 +0200

    Change text auto-fit alg. to also increase the scaling
    
    When in edit mode, the text can be deleted, so the text box size
    can become smaller, but the auto-fit algorithm didn't take into
    account.
    In this case we already have the font and spacing scaling already
    set to a specific value and we need to find a scaling value where
    the margin is the smallest.
    
    This change also adds a test for the issue.
    
    Change-Id: I6c52f06dfbf5a1e582f7b31aceabf4736498ee90
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151412
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/editeng/source/editeng/editeng.cxx 
b/editeng/source/editeng/editeng.cxx
index 5b70a2c2288b..d263363253e1 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -2275,11 +2275,27 @@ void EditEngine::getGlobalSpacingScale(double& rX, 
double& rY) const
     pImpEditEngine->getSpacingScale(rX, rY);
 }
 
+basegfx::B2DTuple EditEngine::getGlobalSpacingScale() const
+{
+    double x = 0.0;
+    double y = 0.0;
+    pImpEditEngine->getSpacingScale(x, y);
+    return {x, y};
+}
+
 void EditEngine::getGlobalFontScale(double& rX, double& rY) const
 {
     pImpEditEngine->getFontScale(rX, rY);
 }
 
+basegfx::B2DTuple EditEngine::getGlobalFontScale() const
+{
+    double x = 0.0;
+    double y = 0.0;
+    pImpEditEngine->getFontScale(x, y);
+    return {x, y};
+}
+
 void EditEngine::setRoundFontSizeToPt(bool bRound) const
 {
     pImpEditEngine->setRoundToNearestPt(bRound);
diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx
index b3d67c1c472e..b31b77160ad5 100644
--- a/include/editeng/editeng.hxx
+++ b/include/editeng/editeng.hxx
@@ -16,7 +16,7 @@
  *   except in compliance with the License. You may obtain a copy of
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
-// MyEDITENG, due to exported EditEng
+
 #ifndef INCLUDED_EDITENG_EDITENG_HXX
 #define INCLUDED_EDITENG_EDITENG_HXX
 
@@ -41,6 +41,7 @@
 #include <tools/degree.hxx>
 #include <tools/long.hxx>
 #include <tools/fontenum.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
 
 #include <editeng/eedata.hxx>
 #include <o3tl/typed_flags_set.hxx>
@@ -418,7 +419,9 @@ public:
     void setGlobalScale(double fFontScaleX, double fFontScaleY, double 
fSpacingScaleX, double fSpacingScaleY);
 
     void getGlobalSpacingScale(double& rX, double& rY) const;
+    basegfx::B2DTuple getGlobalSpacingScale() const;
     void getGlobalFontScale(double& rX, double& rY) const;
+    basegfx::B2DTuple getGlobalFontScale() const;
 
     void setRoundFontSizeToPt(bool bRound) const;
 
diff --git a/sd/CppunitTest_sd_textfitting_tests.mk 
b/sd/CppunitTest_sd_textfitting_tests.mk
new file mode 100644
index 000000000000..20e302d86793
--- /dev/null
+++ b/sd/CppunitTest_sd_textfitting_tests.mk
@@ -0,0 +1,79 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,sd_textfitting_tests))
+
+$(eval $(call gb_CppunitTest_use_externals,sd_textfitting_tests,\
+    boost_headers \
+    libxml2 \
+))
+
+$(eval $(call 
gb_CppunitTest_use_common_precompiled_header,sd_textfitting_tests))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,sd_textfitting_tests, \
+    sd/qa/unit/TextFittingTest \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,sd_textfitting_tests, \
+    basegfx \
+    comphelper \
+    cppu \
+    cppuhelper \
+    drawinglayer \
+    editeng \
+    for \
+    forui \
+    i18nlangtag \
+    msfilter \
+    oox \
+    sal \
+    salhelper \
+    sax \
+    sd \
+    sfx \
+    sot \
+    subsequenttest \
+    svl \
+    svt \
+    svx \
+    svxcore \
+    test \
+    tl \
+    tk \
+    ucbhelper \
+    unotest \
+    utl \
+    vcl \
+    xo \
+))
+
+$(eval $(call gb_CppunitTest_set_include,sd_textfitting_tests,\
+    -I$(SRCDIR)/sd/source/ui/inc \
+    -I$(SRCDIR)/sd/inc \
+    $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,sd_textfitting_tests))
+$(eval $(call gb_CppunitTest_use_ure,sd_textfitting_tests))
+$(eval $(call gb_CppunitTest_use_vcl,sd_textfitting_tests))
+$(eval $(call gb_CppunitTest_use_rdb,sd_textfitting_tests,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,sd_textfitting_tests,\
+    officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,sd_textfitting_tests))
+
+$(eval $(call gb_CppunitTest_add_arguments,sd_textfitting_tests, \
+    
-env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}"
 \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/sd/Module_sd.mk b/sd/Module_sd.mk
index 93cf5e0dc6e8..9b7736a41a5f 100644
--- a/sd/Module_sd.mk
+++ b/sd/Module_sd.mk
@@ -49,6 +49,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sd,\
     CppunitTest_sd_filter_eppt \
     CppunitTest_sd_shape_import_export_tests \
     CppunitTest_sd_a11y \
+    CppunitTest_sd_textfitting_tests \
 ))
 endif
 
diff --git a/sd/qa/unit/TextFittingTest.cxx b/sd/qa/unit/TextFittingTest.cxx
new file mode 100644
index 000000000000..5cbe8a6b9c69
--- /dev/null
+++ b/sd/qa/unit/TextFittingTest.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <officecfg/Office/Common.hxx>
+
+#include "sdmodeltestbase.hxx"
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPages.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/table/XTable.hpp>
+#include <com/sun/star/table/XMergeableCellRange.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+
+#include <DrawDocShell.hxx>
+#include <editeng/editeng.hxx>
+#include <drawdoc.hxx>
+#include <vcl/scheduler.hxx>
+#include <svx/sdr/table/tablecontroller.hxx>
+#include <sfx2/request.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svxids.hrc>
+#include <editeng/eeitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/outlobj.hxx>
+#include <editeng/editobj.hxx>
+#include <undo/undomanager.hxx>
+#include <GraphicViewShell.hxx>
+#include <sdpage.hxx>
+#include <comphelper/base64.hxx>
+#include <LayerTabBar.hxx>
+#include <vcl/event.hxx>
+#include <vcl/keycodes.hxx>
+#include <svx/svdoashp.hxx>
+#include <tools/gen.hxx>
+#include <svx/view3d.hxx>
+#include <svx/scene3d.hxx>
+#include <svx/sdmetitm.hxx>
+#include <unomodel.hxx>
+
+using namespace css;
+
+class TextFittingTest : public SdModelTestBase
+{
+public:
+    TextFittingTest()
+        : SdModelTestBase("/sd/qa/unit/data/")
+    {
+    }
+};
+
+CPPUNIT_TEST_FIXTURE(TextFittingTest, testTest)
+{
+    createSdImpressDoc("TextFitting.odp");
+
+    SdXImpressDocument* pXImpressDocument = 
dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pXImpressDocument);
+    sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
+    SdPage* pPage = pViewShell->GetActualPage();
+    auto pTextObject = DynCastSdrTextObj(pPage->GetObj(0));
+    CPPUNIT_ASSERT(pTextObject);
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetFontScale(), 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetSpacingScale(), 1E-2);
+
+    {
+        OutlinerParaObject* pOutlinerParagraphObject = 
pTextObject->GetOutlinerParaObject();
+        const EditTextObject& aEdit = 
pOutlinerParagraphObject->GetTextObject();
+        CPPUNIT_ASSERT_EQUAL(OUString(u"D1"), aEdit.GetText(0));
+        CPPUNIT_ASSERT_EQUAL(OUString(u"D2"), aEdit.GetText(1));
+        CPPUNIT_ASSERT_EQUAL(OUString(u"D3"), aEdit.GetText(2));
+    }
+
+    sd::ViewShell* pViewShell1 = 
pXImpressDocument->GetDocShell()->GetViewShell();
+    SdrView* pView1 = pViewShell1->GetView();
+    Scheduler::ProcessEventsToIdle();
+    pView1->SdrBeginTextEdit(pTextObject);
+    CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+
+    auto* pOLV = pView1->GetTextEditOutlinerView();
+    CPPUNIT_ASSERT(pOLV);
+    auto& rEditView = pOLV->GetEditView();
+    auto* pEditEngine = rEditView.GetEditEngine();
+    CPPUNIT_ASSERT(pEditEngine);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pEditEngine->GetParagraphCount());
+
+    // Add paragraph 4
+    rEditView.SetSelection(ESelection(3, 0, 3, 0));
+    rEditView.InsertText(u"\nD4");
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pEditEngine->GetParagraphCount());
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(87.49, 
pEditEngine->getGlobalFontScale().getY(), 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(90.0, 
pEditEngine->getGlobalSpacingScale().getY(), 1E-2);
+
+    // Add paragraph 5
+    rEditView.SetSelection(ESelection(4, 0, 4, 0));
+    rEditView.InsertText(u"\nD5");
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pEditEngine->GetParagraphCount());
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(54.68, 
pEditEngine->getGlobalFontScale().getY(), 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
pEditEngine->getGlobalSpacingScale().getY(), 1E-2);
+
+    // Add paragraph 6
+    rEditView.SetSelection(ESelection(5, 0, 5, 0));
+    rEditView.InsertText(u"\nD6");
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), pEditEngine->GetParagraphCount());
+
+    // Delete paragraph 6
+    rEditView.SetSelection(ESelection(4, EE_TEXTPOS_MAX_COUNT, 5, 
EE_TEXTPOS_MAX_COUNT));
+    rEditView.DeleteSelected();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pEditEngine->GetParagraphCount());
+
+    // Delete paragraph 5
+    rEditView.SetSelection(ESelection(3, EE_TEXTPOS_MAX_COUNT, 4, 
EE_TEXTPOS_MAX_COUNT));
+    rEditView.DeleteSelected();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), pEditEngine->GetParagraphCount());
+
+    // Delete paragraph 4
+    rEditView.SetSelection(ESelection(2, EE_TEXTPOS_MAX_COUNT, 3, 
EE_TEXTPOS_MAX_COUNT));
+    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->getGlobalFontScale().getY(), 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, 
pEditEngine->getGlobalSpacingScale().getY(), 1E-2);
+
+    // are we still in text edit mode?
+    CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+    pView1->SdrEndTextEdit();
+    CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetFontScale(), 1E-2);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, pTextObject->GetSpacingScale(), 1E-2);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/data/TextFitting.odp b/sd/qa/unit/data/TextFitting.odp
new file mode 100644
index 000000000000..1d4d4fd7ef65
Binary files /dev/null and b/sd/qa/unit/data/TextFitting.odp differ
diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx
index f2951787b551..a27e112d85cb 100644
--- a/svx/source/svdraw/svdotext.cxx
+++ b/svx/source/svdraw/svdotext.cxx
@@ -1303,7 +1303,11 @@ void 
SdrTextObj::autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size&
     else
         fCurrentFitFactor = double(rTextBoxSize.Height()) / 
aCurrentTextBoxSize.Height();
 
-    if (fCurrentFitFactor >= 1.0)
+    double fInitialFontScaleY = 0.0;
+    double fInitialSpacing = 0.0;
+    rOutliner.getGlobalScale(o3tl::temporary(double()), fInitialFontScaleY, 
o3tl::temporary(double()), fInitialSpacing);
+
+    if (fCurrentFitFactor >= 1.0 && fInitialFontScaleY >= 100.0 && 
fInitialSpacing >= 100.0)
         return;
 
     sal_Int32 nFontHeight = 
GetObjectItemSet().Get(EE_CHAR_FONTHEIGHT).GetHeight();
@@ -1313,9 +1317,21 @@ void 
SdrTextObj::autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size&
     double fMaxY = fMaxScale;
 
     double fBestFontScale = 0.0;
-    double fBestSpacing = fMaxScale;
+    double fBestSpacing = 100.0;
     double fBestFitFactor = fCurrentFitFactor;
 
+    if (fCurrentFitFactor >= 1.0)
+    {
+        fMinY = fInitialFontScaleY;
+        fBestFontScale = fInitialFontScaleY;
+        fBestSpacing = fInitialSpacing;
+        fBestFitFactor = fCurrentFitFactor;
+    }
+    else
+    {
+        fMaxY = std::min(fInitialFontScaleY, fMaxScale);
+    }
+
     double fInTheMidle = 0.5;
 
     int iteration = 0;

Reply via email to